Auto merge of #137045 - BoxyUwU:defer_repeat_expr_checks, r= · rust-lang/rust@9053a8a (original) (raw)

`@@ -6,10 +6,10 @@ use rustc_errors::codes::*;

`

6

6

`use rustc_errors::{

`

7

7

`Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey, a_or_an, listify, pluralize,

`

8

8

`};

`

9

``

`-

use rustc_hir::def::{CtorOf, DefKind, Res};

`

``

9

`+

use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};

`

10

10

`use rustc_hir::def_id::DefId;

`

11

11

`use rustc_hir::intravisit::Visitor;

`

12

``

`-

use rustc_hir::{ExprKind, HirId, Node, QPath};

`

``

12

`+

use rustc_hir::{ExprKind, HirId, LangItem, Node, QPath};

`

13

13

`use rustc_hir_analysis::check::intrinsicck::InlineAsmCtxt;

`

14

14

`use rustc_hir_analysis::check::potentially_plural_count;

`

15

15

`use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;

`

`@@ -119,6 +119,64 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

`

119

119

`}

`

120

120

`}

`

121

121

``

``

122

`+

pub(in super::super) fn check_repeat_exprs(&self) {

`

``

123

`+

let mut deferred_repeat_expr_checks = self.deferred_repeat_expr_checks.borrow_mut();

`

``

124

`+

debug!("FnCtxt::check_repeat_exprs: {} deferred checks", deferred_repeat_expr_checks.len());

`

``

125

`+

for (element, element_ty, count) in deferred_repeat_expr_checks.drain(..) {

`

``

126

`+

let count = self

`

``

127

`+

.try_structurally_resolve_const(element.span, self.normalize(element.span, count));

`

``

128

+

``

129

`+

// If the length is 0, we don't create any elements, so we don't copy any.

`

``

130

`+

// If the length is 1, we don't copy that one element, we move it. Only check

`

``

131

`` +

// for Copy if the length is larger, or unevaluated.

``

``

132

`+

if count.try_to_target_usize(self.tcx).is_none_or(|x| x > 1) {

`

``

133

`+

self.enforce_repeat_element_needs_copy_bound(element, element_ty);

`

``

134

`+

}

`

``

135

`+

}

`

``

136

`+

}

`

``

137

+

``

138

`` +

/// Requires that element_ty is Copy (unless it's a const expression itself).

``

``

139

`+

fn enforce_repeat_element_needs_copy_bound(

`

``

140

`+

&self,

`

``

141

`+

element: &hir::Expr<'_>,

`

``

142

`+

element_ty: Ty<'tcx>,

`

``

143

`+

) {

`

``

144

`+

let tcx = self.tcx;

`

``

145

`+

// Actual constants as the repeat element get inserted repeatedly instead of getting copied via Copy.

`

``

146

`+

match &element.kind {

`

``

147

`+

hir::ExprKind::ConstBlock(..) => return,

`

``

148

`+

hir::ExprKind::Path(qpath) => {

`

``

149

`+

let res = self.typeck_results.borrow().qpath_res(qpath, element.hir_id);

`

``

150

`+

if let Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::AnonConst, _) = res

`

``

151

`+

{

`

``

152

`+

return;

`

``

153

`+

}

`

``

154

`+

}

`

``

155

`+

_ => {}

`

``

156

`+

}

`

``

157

`+

// If someone calls a const fn or constructs a const value, they can extract that

`

``

158

`+

// out into a separate constant (or a const block in the future), so we check that

`

``

159

`+

// to tell them that in the diagnostic. Does not affect typeck.

`

``

160

`+

let is_constable = match element.kind {

`

``

161

`+

hir::ExprKind::Call(func, _args) => match *self.node_ty(func.hir_id).kind() {

`

``

162

`+

ty::FnDef(def_id, _) if tcx.is_stable_const_fn(def_id) => traits::IsConstable::Fn,

`

``

163

`+

_ => traits::IsConstable::No,

`

``

164

`+

},

`

``

165

`+

hir::ExprKind::Path(qpath) => {

`

``

166

`+

match self.typeck_results.borrow().qpath_res(&qpath, element.hir_id) {

`

``

167

`+

Res::Def(DefKind::Ctor(_, CtorKind::Const), _) => traits::IsConstable::Ctor,

`

``

168

`+

_ => traits::IsConstable::No,

`

``

169

`+

}

`

``

170

`+

}

`

``

171

`+

_ => traits::IsConstable::No,

`

``

172

`+

};

`

``

173

+

``

174

`+

let lang_item = self.tcx.require_lang_item(LangItem::Copy, None);

`

``

175

`+

let code =

`

``

176

`+

traits::ObligationCauseCode::RepeatElementCopy { is_constable, elt_span: element.span };

`

``

177

`+

self.require_type_meets(element_ty, element.span, code, lang_item);

`

``

178

`+

}

`

``

179

+

122

180

`pub(in super::super) fn check_method_argument_types(

`

123

181

`&self,

`

124

182

`sp: Span,

`