@@ -501,28 +501,38 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
501501 // FIXME use place_projection.is_empty() when is available
502502 if let Place :: Base ( _) = place {
503503 if let PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: Copy ) = context {
504- let tcx = self . tcx ( ) ;
505- let trait_ref = ty:: TraitRef {
506- def_id : tcx. lang_items ( ) . copy_trait ( ) . unwrap ( ) ,
507- substs : tcx. mk_substs_trait ( place_ty. ty , & [ ] ) ,
504+ let is_promoted = match place {
505+ Place :: Base ( PlaceBase :: Static ( box Static {
506+ kind : StaticKind :: Promoted ( _) ,
507+ ..
508+ } ) ) => true ,
509+ _ => false ,
508510 } ;
509511
510- // In order to have a Copy operand, the type T of the
511- // value must be Copy. Note that we prove that T: Copy,
512- // rather than using the `is_copy_modulo_regions`
513- // test. This is important because
514- // `is_copy_modulo_regions` ignores the resulting region
515- // obligations and assumes they pass. This can result in
516- // bounds from Copy impls being unsoundly ignored (e.g.,
517- // #29149). Note that we decide to use Copy before knowing
518- // whether the bounds fully apply: in effect, the rule is
519- // that if a value of some type could implement Copy, then
520- // it must.
521- self . cx . prove_trait_ref (
522- trait_ref,
523- location. to_locations ( ) ,
524- ConstraintCategory :: CopyBound ,
525- ) ;
512+ if !is_promoted {
513+ let tcx = self . tcx ( ) ;
514+ let trait_ref = ty:: TraitRef {
515+ def_id : tcx. lang_items ( ) . copy_trait ( ) . unwrap ( ) ,
516+ substs : tcx. mk_substs_trait ( place_ty. ty , & [ ] ) ,
517+ } ;
518+
519+ // In order to have a Copy operand, the type T of the
520+ // value must be Copy. Note that we prove that T: Copy,
521+ // rather than using the `is_copy_modulo_regions`
522+ // test. This is important because
523+ // `is_copy_modulo_regions` ignores the resulting region
524+ // obligations and assumes they pass. This can result in
525+ // bounds from Copy impls being unsoundly ignored (e.g.,
526+ // #29149). Note that we decide to use Copy before knowing
527+ // whether the bounds fully apply: in effect, the rule is
528+ // that if a value of some type could implement Copy, then
529+ // it must.
530+ self . cx . prove_trait_ref (
531+ trait_ref,
532+ location. to_locations ( ) ,
533+ ConstraintCategory :: CopyBound ,
534+ ) ;
535+ }
526536 }
527537 }
528538
@@ -1953,18 +1963,32 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
19531963 }
19541964
19551965 Rvalue :: Repeat ( operand, len) => if * len > 1 {
1956- let operand_ty = operand. ty ( body, tcx) ;
1957-
1958- let trait_ref = ty:: TraitRef {
1959- def_id : tcx. lang_items ( ) . copy_trait ( ) . unwrap ( ) ,
1960- substs : tcx. mk_substs_trait ( operand_ty, & [ ] ) ,
1961- } ;
1962-
1963- self . prove_trait_ref (
1964- trait_ref,
1965- location. to_locations ( ) ,
1966- ConstraintCategory :: CopyBound ,
1967- ) ;
1966+ if let Operand :: Move ( _) = operand {
1967+ // While this is located in `nll::typeck` this error is not an NLL error, it's
1968+ // a required check to make sure that repeated elements implement `Copy`.
1969+ let span = body. source_info ( location) . span ;
1970+ let ty = operand. ty ( body, tcx) ;
1971+ let is_copy = self . infcx . type_is_copy_modulo_regions ( self . param_env , ty, span) ;
1972+ if !is_copy {
1973+ let copy_path = self . tcx ( ) . def_path_str (
1974+ self . tcx ( ) . lang_items ( ) . copy_trait ( ) . unwrap ( ) ) ;
1975+ self . tcx ( ) . sess
1976+ . struct_span_err (
1977+ span,
1978+ & format ! ( "repeated expression does not implement `{}`" , copy_path) ,
1979+ )
1980+ . span_label ( span, & format ! (
1981+ "the trait `{}` is not implemented for `{}`" ,
1982+ copy_path, ty,
1983+ ) )
1984+ . note ( & format ! (
1985+ "the `{}` trait is required because the repeated element will be \
1986+ copied",
1987+ copy_path,
1988+ ) )
1989+ . emit ( ) ;
1990+ }
1991+ }
19681992 } ,
19691993
19701994 Rvalue :: NullaryOp ( _, ty) => {
0 commit comments