@@ -501,28 +501,38 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
501
501
// FIXME use place_projection.is_empty() when is available
502
502
if let Place :: Base ( _) = place {
503
503
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 ,
508
510
} ;
509
511
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
+ }
526
536
}
527
537
}
528
538
@@ -1953,18 +1963,32 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
1953
1963
}
1954
1964
1955
1965
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
+ }
1968
1992
} ,
1969
1993
1970
1994
Rvalue :: NullaryOp ( _, ty) => {
0 commit comments