diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2e51a786f468..49961d02ddab 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -566,7 +566,7 @@ labels to triage issues: to fix the issue. * The dark blue **final-comment-period** label marks bugs that are using the - RFC signoff functionality of [rfcbot][rfcbot] and are currenty in the final + RFC signoff functionality of [rfcbot][rfcbot] and are currently in the final comment period. * Red, **I**-prefixed labels indicate the **importance** of the issue. The diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index e845438c0a83..2bc037e3fee1 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1822,12 +1822,12 @@ impl SpecExtend for Vec unsafe { let mut ptr = self.as_mut_ptr().add(self.len()); let mut local_len = SetLenOnDrop::new(&mut self.len); - for element in iterator { + iterator.for_each(move |element| { ptr::write(ptr, element); ptr = ptr.offset(1); // NB can't overflow since we would have had to alloc the address space local_len.increment_len(1); - } + }); } } else { self.extend_desugared(iterator) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 9c4e995e24d0..388abc88cfd7 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -873,8 +873,8 @@ for ty::TyKind<'gcx> Tuple(inner_tys) => { inner_tys.hash_stable(hcx, hasher); } - Projection(ref projection_ty) => { - projection_ty.hash_stable(hcx, hasher); + Projection(ref data) | UnnormalizedProjection(ref data) => { + data.hash_stable(hcx, hasher); } Opaque(def_id, substs) => { def_id.hash_stable(hcx, hasher); diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index b30ccb5976c9..6449227af4ab 100644 --- a/src/librustc/infer/canonical/canonicalizer.rs +++ b/src/librustc/infer/canonical/canonicalizer.rs @@ -283,6 +283,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> | ty::Never | ty::Tuple(..) | ty::Projection(..) + | ty::UnnormalizedProjection(..) | ty::Foreign(..) | ty::Param(..) | ty::Opaque(..) => { diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs index 1cb813c39e68..e17e777332ec 100644 --- a/src/librustc/infer/freshen.rs +++ b/src/librustc/infer/freshen.rs @@ -193,6 +193,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> { ty::Never | ty::Tuple(..) | ty::Projection(..) | + ty::UnnormalizedProjection(..) | ty::Foreign(..) | ty::Param(..) | ty::Closure(..) | diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index d695ad88e47a..c81d55e69b61 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -171,7 +171,7 @@ impl<'tcx> Scalar { pub fn from_uint(i: impl Into, size: Size) -> Self { let i = i.into(); debug_assert_eq!(truncate(i, size), i, - "Unsigned value {} does not fit in {} bits", i, size.bits()); + "Unsigned value {} does not fit in {} bits", i, size.bits()); Scalar::Bits { bits: i, size: size.bytes() as u8 } } @@ -181,7 +181,7 @@ impl<'tcx> Scalar { // `into` performed sign extension, we have to truncate let truncated = truncate(i as u128, size); debug_assert_eq!(sign_extend(truncated, size) as i128, i, - "Signed value {} does not fit in {} bits", i, size.bits()); + "Signed value {} does not fit in {} bits", i, size.bits()); Scalar::Bits { bits: truncated, size: size.bytes() as u8 } } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 27ef01b93cda..30117f90dc69 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -12,7 +12,6 @@ //! //! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir/index.html -use graphviz::IntoCow; use hir::def::CtorKind; use hir::def_id::DefId; use hir::{self, HirId, InlineAsm}; @@ -327,22 +326,20 @@ impl<'tcx> Mir<'tcx> { if idx < stmts.len() { &stmts[idx].source_info } else { - assert!(idx == stmts.len()); + assert_eq!(idx, stmts.len()); &block.terminator().source_info } } /// Check if `sub` is a sub scope of `sup` pub fn is_sub_scope(&self, mut sub: SourceScope, sup: SourceScope) -> bool { - loop { - if sub == sup { - return true; - } + while sub != sup { match self.source_scopes[sub].parent_scope { None => return false, Some(p) => sub = p, } } + true } /// Return the return type, it always return first element from `local_decls` array @@ -526,9 +523,7 @@ impl BorrowKind { pub fn allows_two_phase_borrow(&self) -> bool { match *self { BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => false, - BorrowKind::Mut { - allow_two_phase_borrow, - } => allow_two_phase_borrow, + BorrowKind::Mut { allow_two_phase_borrow } => allow_two_phase_borrow, } } } @@ -1574,42 +1569,42 @@ impl<'tcx> TerminatorKind<'tcx> { }; fmt_const_val(&mut s, &c).unwrap(); s.into() - }).chain(iter::once(String::from("otherwise").into())) + }).chain(iter::once("otherwise".into())) .collect() } Call { destination: Some(_), cleanup: Some(_), .. - } => vec!["return".into_cow(), "unwind".into_cow()], + } => vec!["return".into(), "unwind".into()], Call { destination: Some(_), cleanup: None, .. - } => vec!["return".into_cow()], + } => vec!["return".into()], Call { destination: None, cleanup: Some(_), .. - } => vec!["unwind".into_cow()], + } => vec!["unwind".into()], Call { destination: None, cleanup: None, .. } => vec![], - Yield { drop: Some(_), .. } => vec!["resume".into_cow(), "drop".into_cow()], - Yield { drop: None, .. } => vec!["resume".into_cow()], + Yield { drop: Some(_), .. } => vec!["resume".into(), "drop".into()], + Yield { drop: None, .. } => vec!["resume".into()], DropAndReplace { unwind: None, .. } | Drop { unwind: None, .. } => { - vec!["return".into_cow()] + vec!["return".into()] } DropAndReplace { unwind: Some(_), .. } | Drop { unwind: Some(_), .. - } => vec!["return".into_cow(), "unwind".into_cow()], + } => vec!["return".into(), "unwind".into()], Assert { cleanup: None, .. } => vec!["".into()], - Assert { .. } => vec!["success".into_cow(), "unwind".into_cow()], + Assert { .. } => vec!["success".into(), "unwind".into()], FalseEdges { ref imaginary_targets, .. diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs index 4d353a36db02..7520695a7cd9 100644 --- a/src/librustc/mir/mono.rs +++ b/src/librustc/mir/mono.rs @@ -325,7 +325,7 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a> CodegenUnitNameBuilder<'a, 'gcx, 'tcx> { String::new() }; - let crate_disambiguator = format!("{}", tcx.crate_disambiguator(cnum)); + let crate_disambiguator = tcx.crate_disambiguator(cnum).to_string(); // Using a shortened disambiguator of about 40 bits format!("{}.{}{}", tcx.crate_name(cnum), diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index 2a25e057a714..fc7b4862b0ae 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -87,8 +87,8 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> { assert!(index < adt_def.variants.len()); assert_eq!(adt_def, adt_def1); PlaceTy::Downcast { adt_def, - substs, - variant_index: index } + substs, + variant_index: index } } _ => { bug!("cannot downcast non-ADT type: `{:?}`", self) @@ -151,7 +151,7 @@ impl<'tcx> Place<'tcx> { } }, _ => None, - } + } _ => None, } } @@ -255,9 +255,9 @@ impl<'tcx> Operand<'tcx> { impl<'tcx> BinOp { pub fn ty<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, - lhs_ty: Ty<'tcx>, - rhs_ty: Ty<'tcx>) - -> Ty<'tcx> { + lhs_ty: Ty<'tcx>, + rhs_ty: Ty<'tcx>) + -> Ty<'tcx> { // FIXME: handle SIMD correctly match self { &BinOp::Add | &BinOp::Sub | &BinOp::Mul | &BinOp::Div | &BinOp::Rem | diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index 7401d4099ff6..caf549e37a90 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -475,6 +475,7 @@ fn ty_is_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> bool { ty::Error => true, + ty::UnnormalizedProjection(..) | ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) | diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 7695f26d7011..3b3e38a8bb7c 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -269,7 +269,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ty::Generator(..) => Some(18), ty::Foreign(..) => Some(19), ty::GeneratorWitness(..) => Some(20), - ty::Infer(..) | ty::Error => None + ty::Infer(..) | ty::Error => None, + ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), } } diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 0f330504334a..e6bf02cd73e0 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -292,7 +292,7 @@ impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx, ty::Predicate::Trait(ref data) => { let trait_obligation = obligation.with(data.clone()); - if data.is_global() && !data.has_late_bound_regions() { + if data.is_global() { // no type variables present, can use evaluation for better caching. // FIXME: consider caching errors too. if self.selcx.infcx().predicate_must_hold(&obligation) { @@ -362,6 +362,7 @@ impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx, match binder.no_late_bound_regions() { // If so, this obligation is an error (for now). Eventually we should be // able to support additional cases here, like `for<'a> &'a str: 'a`. + // NOTE: this is duplicate-implemented between here and fulfillment. None => { ProcessResult::Error(CodeSelectionError(Unimplemented)) } diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs index f5fb183ec1a5..aaf03f8e7fb5 100644 --- a/src/librustc/traits/query/dropck_outlives.rs +++ b/src/librustc/traits/query/dropck_outlives.rs @@ -253,5 +253,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) -> | ty::Opaque(..) | ty::Infer(_) | ty::Generator(..) => false, + + ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), } } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 268b8e0161b6..c9fa960a3656 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -690,10 +690,92 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } } - ty::Predicate::TypeOutlives(..) | ty::Predicate::RegionOutlives(..) => { - // we do not consider region relationships when - // evaluating trait matches - Ok(EvaluatedToOk) + ty::Predicate::TypeOutlives(ref binder) => { + assert!(!binder.has_escaping_regions()); + // Check if the type has higher-ranked regions. + if binder.skip_binder().0.has_escaping_regions() { + // If so, this obligation is an error (for now). Eventually we should be + // able to support additional cases here, like `for<'a> &'a str: 'a`. + + // NOTE: this hack is implemented in both trait fulfillment and + // evaluation. If you fix it in one place, make sure you fix it + // in the other. + + // We don't want to allow this sort of reasoning in intercrate + // mode, for backwards-compatibility reasons. + if self.intercrate.is_some() { + Ok(EvaluatedToAmbig) + } else { + Ok(EvaluatedToErr) + } + } else { + // If the type has no late bound regions, then if we assign all + // the inference variables in it to be 'static, then the type + // will be 'static itself. + // + // Therefore, `staticize(T): 'a` holds for any `'a`, so this + // obligation is fulfilled. Because evaluation works with + // staticized types (yes I know this is involved with #21974), + // we are 100% OK here. + Ok(EvaluatedToOk) + } + } + + ty::Predicate::RegionOutlives(ref binder) => { + let ty::OutlivesPredicate(r_a, r_b) = binder.skip_binder(); + + if r_a == r_b { + // for<'a> 'a: 'a. OK + Ok(EvaluatedToOk) + } else if **r_a == ty::ReStatic { + // 'static: 'x always holds. + // + // This special case is handled somewhat inconsistently - if we + // have an inference variable that is supposed to be equal to + // `'static`, then we don't allow it to be equated to an LBR, + // but if we have a literal `'static`, then we *do*. + // + // This is actually consistent with how our region inference works. + // + // It would appear that this sort of inconsistency would + // cause "instability" problems with evaluation caching. However, + // evaluation caching is only for trait predicates, and when + // trait predicates create nested obligations, they contain + // inference variables for all the regions in the trait - the + // only way this codepath can be reached from trait predicate + // evaluation is when the user typed an explicit `where 'static: 'a` + // lifetime bound (in which case we want to return EvaluatedToOk). + // + // If we ever want to handle inference variables that might be + // equatable with ReStatic, we need to make sure we are not confused by + // technically-allowed-by-RFC-447-but-probably-should-not-be + // impls such as + // ```Rust + // impl<'a, 's, T> X<'s> for T where T: Debug + 'a, 'a: 's + // ``` + Ok(EvaluatedToOk) + } else if r_a.is_late_bound() || r_b.is_late_bound() { + // There is no current way to prove `for<'a> 'a: 'x` + // unless `'a = 'x`, because there are no bounds involving + // lifetimes. + + // It might be possible to prove `for<'a> 'x: 'a` by forcing `'x` + // to be `'static`. However, this is not currently done by type + // inference unless `'x` is literally ReStatic. See the comment + // above. + + // We don't want to allow this sort of reasoning in intercrate + // mode, for backwards-compatibility reasons. + if self.intercrate.is_some() { + Ok(EvaluatedToAmbig) + } else { + Ok(EvaluatedToErr) + } + } else { + // Relating 2 inference variable regions. These will + // always hold if our query is "staticized". + Ok(EvaluatedToOk) + } } ty::Predicate::ObjectSafe(trait_def_id) => { @@ -900,6 +982,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { { debug!("evaluate_stack({:?}) --> recursive", stack.fresh_trait_ref); + let cycle = stack.iter().skip(1).take(rec_index + 1); let cycle = cycle.map(|stack| ty::Predicate::Trait(stack.obligation.predicate)); if self.coinductive_match(cycle) { @@ -2200,6 +2283,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => None, ty::Infer(ty::TyVar(_)) => Ambiguous, + ty::UnnormalizedProjection(..) | ty::Infer(ty::CanonicalTy(_)) | ty::Infer(ty::FreshTy(_)) | ty::Infer(ty::FreshIntTy(_)) | @@ -2272,6 +2356,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { Ambiguous } + ty::UnnormalizedProjection(..) | ty::Infer(ty::CanonicalTy(_)) | ty::Infer(ty::FreshTy(_)) | ty::Infer(ty::FreshIntTy(_)) | @@ -2310,6 +2395,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { Vec::new() } + ty::UnnormalizedProjection(..) | ty::Dynamic(..) | ty::Param(..) | ty::Foreign(..) | diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 64e9d15092eb..29b3db400b11 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2266,7 +2266,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { self, Adt, Array, Slice, RawPtr, Ref, FnDef, FnPtr, Generator, GeneratorWitness, Dynamic, Closure, Tuple, - Param, Infer, Projection, Opaque, Foreign); + Param, Infer, UnnormalizedProjection, Projection, Opaque, Foreign); println!("Substs interner: #{}", self.interners.substs.borrow().len()); println!("Region interner: #{}", self.interners.region.borrow().len()); diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 9f9d918415e7..b3a1b312ca1d 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -222,6 +222,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { ty::Infer(ty::FreshIntTy(_)) => "skolemized integral type".to_string(), ty::Infer(ty::FreshFloatTy(_)) => "skolemized floating-point type".to_string(), ty::Projection(_) => "associated type".to_string(), + ty::UnnormalizedProjection(_) => "non-normalized associated type".to_string(), ty::Param(ref p) => { if p.is_self() { "Self".to_string() diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index 2d055fd307dc..0f68e7aba4de 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -103,6 +103,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, ty::FnPtr(ref f) => { Some(FunctionSimplifiedType(f.skip_binder().inputs().len())) } + ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), ty::Projection(_) | ty::Param(_) => { if can_simplify_params { // In normalized types, projections don't unify with diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 08d105782387..3ccc24e73a5c 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -150,6 +150,8 @@ impl FlagComputation { self.add_projection_ty(data); } + &ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), + &ty::Opaque(_, substs) => { self.add_flags(TypeFlags::HAS_PROJECTION); self.add_substs(substs); diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index c8d104e6c321..46d133224f81 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -463,6 +463,7 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option { ty::Str | ty::FnPtr(_) | ty::Projection(_) | + ty::UnnormalizedProjection(..) | ty::Param(_) | ty::Opaque(..) | ty::Infer(_) | diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 8bfe46568eb1..7df8af5fa2e7 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1123,7 +1123,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { } tcx.layout_raw(param_env.and(normalized))? } - ty::GeneratorWitness(..) | ty::Infer(_) => { + ty::UnnormalizedProjection(..) | ty::GeneratorWitness(..) | ty::Infer(_) => { bug!("LayoutDetails::compute: unexpected type `{}`", ty) } ty::Param(_) | ty::Error => { @@ -1702,8 +1702,8 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> } } - ty::Projection(_) | ty::Opaque(..) | ty::Param(_) | - ty::Infer(_) | ty::Error => { + ty::Projection(_) | ty::UnnormalizedProjection(..) | + ty::Opaque(..) | ty::Param(_) | ty::Infer(_) | ty::Error => { bug!("TyLayout::field_type: unexpected type `{}`", this.ty) } }) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index b2281691bd66..77e0b9e91bce 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2339,6 +2339,8 @@ impl<'a, 'gcx, 'tcx> AdtDef { vec![ty] } + UnnormalizedProjection(..) => bug!("only used with chalk-engine"), + Param(..) => { // perf hack: if there is a `T: Sized` bound, then // we know that `T` is Sized and do not need to check diff --git a/src/librustc/ty/outlives.rs b/src/librustc/ty/outlives.rs index 68f670708768..91eda66e08c6 100644 --- a/src/librustc/ty/outlives.rs +++ b/src/librustc/ty/outlives.rs @@ -124,6 +124,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } + ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), + // We assume that inference variables are fully resolved. // So, if we encounter an inference variable, just record // the unresolved variable as a component. diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index aab268c07c4f..c3c4cbed89d8 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -876,6 +876,9 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { ty::GeneratorWitness(types) => ty::GeneratorWitness(types.fold_with(folder)), ty::Closure(did, substs) => ty::Closure(did, substs.fold_with(folder)), ty::Projection(ref data) => ty::Projection(data.fold_with(folder)), + ty::UnnormalizedProjection(ref data) => { + ty::UnnormalizedProjection(data.fold_with(folder)) + } ty::Opaque(did, substs) => ty::Opaque(did, substs.fold_with(folder)), ty::Bool | ty::Char | ty::Str | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Error | ty::Infer(_) | @@ -910,7 +913,9 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { } ty::GeneratorWitness(ref types) => types.visit_with(visitor), ty::Closure(_did, ref substs) => substs.visit_with(visitor), - ty::Projection(ref data) => data.visit_with(visitor), + ty::Projection(ref data) | ty::UnnormalizedProjection(ref data) => { + data.visit_with(visitor) + } ty::Opaque(_, ref substs) => substs.visit_with(visitor), ty::Bool | ty::Char | ty::Str | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Error | ty::Infer(_) | diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 6c40dd892391..06d559fd9dbe 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -157,6 +157,11 @@ pub enum TyKind<'tcx> { /// `>::N`. Projection(ProjectionTy<'tcx>), + /// A placeholder type used when we do not have enough information + /// to normalize the projection of an associated type to an + /// existing concrete type. Currently only used with chalk-engine. + UnnormalizedProjection(ProjectionTy<'tcx>), + /// Opaque (`impl Trait`) type found in a return type. /// The `DefId` comes either from /// * the `impl Trait` ast::Ty node, @@ -1806,7 +1811,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { Generator(_, GeneratorSubsts { ref substs }, _) => { substs.regions().collect() } - Projection(ref data) => { + Projection(ref data) | UnnormalizedProjection(ref data) => { data.substs.regions().collect() } FnDef(..) | @@ -1886,6 +1891,8 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => false, + ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), + ty::Infer(ty::TyVar(_)) => false, ty::Infer(ty::CanonicalTy(_)) | diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 93fc77359e43..4d7bab3cf433 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -958,6 +958,8 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty::Dynamic(..) | ty::Projection(..) | ty::Param(_) | ty::Opaque(..) | ty::Infer(_) | ty::Error => true, + ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), + // Structural recursion. ty::Array(ty, _) | ty::Slice(ty) => needs_drop(ty), diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index cf87c2d45747..d20c4f716429 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -97,7 +97,7 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) { ty::Ref(_, ty, _) => { stack.push(ty); } - ty::Projection(ref data) => { + ty::Projection(ref data) | ty::UnnormalizedProjection(ref data) => { stack.extend(data.substs.types().rev()); } ty::Dynamic(ref obj, ..) => { diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index 63206a660df4..397c63a149a4 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -289,6 +289,8 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { self.compute_projection(data); } + ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), + ty::Adt(def, substs) => { // WfNominalType let obligations = self.nominal_obligations(def.did, substs); diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 10382008e0d4..814f8880bbf2 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -18,7 +18,7 @@ use ty::{Bool, Char, Adt}; use ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr}; use ty::{Param, RawPtr, Ref, Never, Tuple}; use ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque}; -use ty::{Dynamic, Int, Uint, Infer}; +use ty::{UnnormalizedProjection, Dynamic, Int, Uint, Infer}; use ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind}; use util::nodemap::FxHashSet; @@ -1143,6 +1143,11 @@ define_print! { } Foreign(def_id) => parameterized(f, subst::Substs::empty(), def_id, &[]), Projection(ref data) => data.print(f, cx), + UnnormalizedProjection(ref data) => { + write!(f, "Unnormalized(")?; + data.print(f, cx)?; + write!(f, ")") + } Opaque(def_id, substs) => { if cx.is_verbose { return write!(f, "Opaque({:?}, {:?})", def_id, substs); diff --git a/src/librustc_codegen_llvm/debuginfo/type_names.rs b/src/librustc_codegen_llvm/debuginfo/type_names.rs index f9eb80a1988a..2f110fd552a8 100644 --- a/src/librustc_codegen_llvm/debuginfo/type_names.rs +++ b/src/librustc_codegen_llvm/debuginfo/type_names.rs @@ -173,6 +173,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, } ty::Error | ty::Infer(_) | + ty::UnnormalizedProjection(..) | ty::Projection(..) | ty::Opaque(..) | ty::GeneratorWitness(..) | diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 01d4d0f8cdb6..a441f7a87f76 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -722,6 +722,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) | + ty::UnnormalizedProjection(..) | ty::Projection(..) | ty::Opaque(..) | ty::FnDef(..) => bug!("Unexpected type in foreign function"), diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 11e27a597fbc..222d1164667d 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -971,7 +971,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { /// Undefined bytes impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { - // FIXME(solson): This is a very naive, slow version. + // FIXME: Add a fast version for the common, nonoverlapping case fn copy_undef_mask( &mut self, src: Pointer, diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs index 3f5a05f9d0ed..f0ea93bfffd3 100644 --- a/src/librustc_mir/monomorphize/item.rs +++ b/src/librustc_mir/monomorphize/item.rs @@ -382,6 +382,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { } ty::Error | ty::Infer(_) | + ty::UnnormalizedProjection(..) | ty::Projection(..) | ty::Param(_) | ty::GeneratorWitness(_) | diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs index e3ec2e6b9ce0..2996fe032004 100644 --- a/src/librustc_traits/dropck_outlives.rs +++ b/src/librustc_traits/dropck_outlives.rs @@ -272,6 +272,8 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>( overflows: vec![], }), + ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), + ty::Infer(..) | ty::Error => { // By the time this code runs, all type variables ought to // be fully resolved. diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 564ecae15dc3..285fed9544dd 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -124,6 +124,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty::Foreign(..) => Some(PointerKind::Thin), // We should really try to normalize here. ty::Projection(ref pi) => Some(PointerKind::OfProjection(pi)), + ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), ty::Opaque(def_id, substs) => Some(PointerKind::OfOpaque(def_id, substs)), ty::Param(ref p) => Some(PointerKind::OfParam(p)), // Insufficient type information. diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 71c78e7f87c0..85b6bcbd144f 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -309,11 +309,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; if self.can_coerce(ref_ty, expected) { if let Ok(src) = cm.span_to_snippet(sp) { - let sugg_expr = match expr.node { // parenthesize if needed (Issue #46756) + let needs_parens = match expr.node { + // parenthesize if needed (Issue #46756) hir::ExprKind::Cast(_, _) | - hir::ExprKind::Binary(_, _, _) => format!("({})", src), - _ => src, + hir::ExprKind::Binary(_, _, _) => true, + // parenthesize borrows of range literals (Issue #54505) + _ if self.is_range_literal(expr) => true, + _ => false, }; + let sugg_expr = if needs_parens { + format!("({})", src) + } else { + src + }; + if let Some(sugg) = self.can_use_as_ref(expr) { return Some(sugg); } @@ -374,6 +383,66 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { None } + /// This function checks if the specified expression is a built-in range literal. + /// (See: `LoweringContext::lower_expr()` in `src/librustc/hir/lowering.rs`). + fn is_range_literal(&self, expr: &hir::Expr) -> bool { + use hir::{Path, QPath, ExprKind, TyKind}; + + // We support `::std::ops::Range` and `::core::ops::Range` prefixes + let is_range_path = |path: &Path| { + let mut segs = path.segments.iter() + .map(|seg| seg.ident.as_str()); + + if let (Some(root), Some(std_core), Some(ops), Some(range), None) = + (segs.next(), segs.next(), segs.next(), segs.next(), segs.next()) + { + // "{{root}}" is the equivalent of `::` prefix in Path + root == "{{root}}" && (std_core == "std" || std_core == "core") + && ops == "ops" && range.starts_with("Range") + } else { + false + } + }; + + let span_is_range_literal = |span: &Span| { + // Check whether a span corresponding to a range expression + // is a range literal, rather than an explicit struct or `new()` call. + let source_map = self.tcx.sess.source_map(); + let end_point = source_map.end_point(*span); + + if let Ok(end_string) = source_map.span_to_snippet(end_point) { + !(end_string.ends_with("}") || end_string.ends_with(")")) + } else { + false + } + }; + + match expr.node { + // All built-in range literals but `..=` and `..` desugar to Structs + ExprKind::Struct(QPath::Resolved(None, ref path), _, _) | + // `..` desugars to its struct path + ExprKind::Path(QPath::Resolved(None, ref path)) => { + return is_range_path(&path) && span_is_range_literal(&expr.span); + } + + // `..=` desugars into `::std::ops::RangeInclusive::new(...)` + ExprKind::Call(ref func, _) => { + if let ExprKind::Path(QPath::TypeRelative(ref ty, ref segment)) = func.node { + if let TyKind::Path(QPath::Resolved(None, ref path)) = ty.node { + let call_to_new = segment.ident.as_str() == "new"; + + return is_range_path(&path) && span_is_range_literal(&expr.span) + && call_to_new; + } + } + } + + _ => {} + } + + false + } + pub fn check_for_cast(&self, err: &mut DiagnosticBuilder<'tcx>, expr: &hir::Expr, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 17e0b0431da6..f96c85ae7ae3 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1637,9 +1637,39 @@ fn explicit_predicates_of<'a, 'tcx>( def_id: DefId, ) -> ty::GenericPredicates<'tcx> { use rustc::hir::*; + use rustc_data_structures::fx::FxHashSet; debug!("explicit_predicates_of(def_id={:?})", def_id); + /// A data structure with unique elements, which preserves order of insertion. + /// Preserving the order of insertion is important here so as not to break + /// compile-fail UI tests. + struct UniquePredicates<'tcx> { + predicates: Vec<(ty::Predicate<'tcx>, Span)>, + uniques: FxHashSet<(ty::Predicate<'tcx>, Span)>, + } + + impl<'tcx> UniquePredicates<'tcx> { + fn new() -> Self { + UniquePredicates { + predicates: vec![], + uniques: FxHashSet::default(), + } + } + + fn push(&mut self, value: (ty::Predicate<'tcx>, Span)) { + if self.uniques.insert(value) { + self.predicates.push(value); + } + } + + fn extend, Span)>>(&mut self, iter: I) { + for value in iter { + self.push(value); + } + } + } + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); let node = tcx.hir.get(node_id); @@ -1649,7 +1679,7 @@ fn explicit_predicates_of<'a, 'tcx>( let icx = ItemCtxt::new(tcx, def_id); let no_generics = hir::Generics::empty(); - let mut predicates = vec![]; + let mut predicates = UniquePredicates::new(); let ast_generics = match node { Node::TraitItem(item) => &item.generics, @@ -1744,7 +1774,7 @@ fn explicit_predicates_of<'a, 'tcx>( // on a trait we need to add in the supertrait bounds and bounds found on // associated types. if let Some((_trait_ref, _)) = is_trait { - predicates = tcx.super_predicates_of(def_id).predicates; + predicates.extend(tcx.super_predicates_of(def_id).predicates); } // In default impls, we can assume that the self type implements @@ -1895,6 +1925,8 @@ fn explicit_predicates_of<'a, 'tcx>( })) } + let mut predicates = predicates.predicates; + // Subtle: before we store the predicates into the tcx, we // sort them so that predicates like `T: Foo` come // before uses of `U`. This avoids false ambiguity errors diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 95544da0b8e0..1125de55a066 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -336,6 +336,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { // types, where we use Error as the Self type } + ty::UnnormalizedProjection(..) | ty::GeneratorWitness(..) | ty::Infer(..) => { bug!("unexpected type encountered in \ diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 371b631723a3..9b305ad03b05 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2737,6 +2737,7 @@ impl<'tcx> Clean for Ty<'tcx> { ty::Closure(..) | ty::Generator(..) => Tuple(vec![]), // FIXME(pcwalton) + ty::UnnormalizedProjection(..) => panic!("UnnormalizedProjection"), ty::GeneratorWitness(..) => panic!("GeneratorWitness"), ty::Infer(..) => panic!("Infer"), ty::Error => panic!("Error"), diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 3de4a1bd4170..7a5353bb60ff 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -217,6 +217,35 @@ pub trait Error: Debug + Display { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, E: Error + 'a> From for Box { + /// Converts a type of [`Error`] into a box of dyn [`Error`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::fmt; + /// use std::mem; + /// + /// #[derive(Debug)] + /// struct AnError; + /// + /// impl fmt::Display for AnError { + /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + /// write!(f , "An error") + /// } + /// } + /// + /// impl Error for AnError { + /// fn description(&self) -> &str { + /// "Description of an error" + /// } + /// } + /// + /// let an_error = AnError; + /// assert!(0 == mem::size_of_val(&an_error)); + /// let a_boxed_error = Box::::from(an_error); + /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` fn from(err: E) -> Box { Box::new(err) } @@ -224,6 +253,41 @@ impl<'a, E: Error + 'a> From for Box { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, E: Error + Send + Sync + 'a> From for Box { + /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of dyn [`Error`] + + /// [`Send`] + [`Sync`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::fmt; + /// use std::mem; + /// + /// #[derive(Debug)] + /// struct AnError; + /// + /// impl fmt::Display for AnError { + /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + /// write!(f , "An error") + /// } + /// } + /// + /// impl Error for AnError { + /// fn description(&self) -> &str { + /// "Description of an error" + /// } + /// } + /// + /// unsafe impl Send for AnError {} + /// + /// unsafe impl Sync for AnError {} + /// + /// let an_error = AnError; + /// assert!(0 == mem::size_of_val(&an_error)); + /// let a_boxed_error = Box::::from(an_error); + /// assert!( + /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` fn from(err: E) -> Box { Box::new(err) } @@ -231,6 +295,19 @@ impl<'a, E: Error + Send + Sync + 'a> From for Box for Box { + /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// + /// let a_string_error = "a string error".to_string(); + /// let a_boxed_error = Box::::from(a_string_error); + /// assert!( + /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` fn from(err: String) -> Box { #[derive(Debug)] struct StringError(String); @@ -251,6 +328,18 @@ impl From for Box { #[stable(feature = "string_box_error", since = "1.6.0")] impl From for Box { + /// Converts a [`String`] into a box of dyn [`Error`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// + /// let a_string_error = "a string error".to_string(); + /// let a_boxed_error = Box::::from(a_string_error); + /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` fn from(str_err: String) -> Box { let err1: Box = From::from(str_err); let err2: Box = err1; @@ -260,6 +349,19 @@ impl From for Box { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, 'b> From<&'b str> for Box { + /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// + /// let a_str_error = "a str error"; + /// let a_boxed_error = Box::::from(a_str_error); + /// assert!( + /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` fn from(err: &'b str) -> Box { From::from(String::from(err)) } @@ -267,6 +369,18 @@ impl<'a, 'b> From<&'b str> for Box { #[stable(feature = "string_box_error", since = "1.6.0")] impl<'a> From<&'a str> for Box { + /// Converts a [`str`] into a box of dyn [`Error`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// + /// let a_str_error = "a str error"; + /// let a_boxed_error = Box::::from(a_str_error); + /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` fn from(err: &'a str) -> Box { From::from(String::from(err)) } @@ -274,6 +388,20 @@ impl<'a> From<&'a str> for Box { #[stable(feature = "cow_box_error", since = "1.22.0")] impl<'a, 'b> From> for Box { + /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// use std::borrow::Cow; + /// + /// let a_cow_str_error = Cow::from("a str error"); + /// let a_boxed_error = Box::::from(a_cow_str_error); + /// assert!( + /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` fn from(err: Cow<'b, str>) -> Box { From::from(String::from(err)) } @@ -281,6 +409,19 @@ impl<'a, 'b> From> for Box { #[stable(feature = "cow_box_error", since = "1.22.0")] impl<'a> From> for Box { + /// Converts a [`Cow`] into a box of dyn [`Error`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// use std::borrow::Cow; + /// + /// let a_cow_str_error = Cow::from("a str error"); + /// let a_boxed_error = Box::::from(a_cow_str_error); + /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` fn from(err: Cow<'a, str>) -> Box { From::from(String::from(err)) } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index f2acdb3f469d..83a05921510b 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2228,6 +2228,9 @@ impl<'a> State<'a> { self.word_nbsp("async")?; self.print_capture_clause(capture_clause)?; self.s.space()?; + // cbox/ibox in analogy to the `ExprKind::Block` arm above + self.cbox(INDENT_UNIT)?; + self.ibox(0)?; self.print_block_with_attrs(blk, attrs)?; } ast::ExprKind::Assign(ref lhs, ref rhs) => { diff --git a/src/test/pretty/issue-54752-async-block.rs b/src/test/pretty/issue-54752-async-block.rs new file mode 100644 index 000000000000..6930ee1a386f --- /dev/null +++ b/src/test/pretty/issue-54752-async-block.rs @@ -0,0 +1,7 @@ +#![feature(async_await)] +#![allow(unused_parens)] + +// edition:2018 +// pp-exact + +fn main() { let _a = (async { }); } diff --git a/src/test/ui/chalkify/lower_env1.stderr b/src/test/ui/chalkify/lower_env1.stderr index d6673f6a8a6f..4a3e14ac0347 100644 --- a/src/test/ui/chalkify/lower_env1.stderr +++ b/src/test/ui/chalkify/lower_env1.stderr @@ -5,9 +5,8 @@ LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar). - = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar). = note: Implemented(Self: Bar) :- FromEnv(Self: Bar). - = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo), WellFormed(Self: Foo). + = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo). error: program clause dump --> $DIR/lower_env1.rs:19:1 @@ -16,11 +15,10 @@ LL | #[rustc_dump_env_program_clauses] //~ ERROR program clause dump | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar). - = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar). = note: Implemented(Self: Bar) :- FromEnv(Self: Bar). = note: Implemented(Self: Foo) :- FromEnv(Self: Foo). = note: Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized). - = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo), WellFormed(Self: Foo). + = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo). = note: WellFormed(Self: Foo) :- Implemented(Self: Foo). = note: WellFormed(Self: std::marker::Sized) :- Implemented(Self: std::marker::Sized). diff --git a/src/test/ui/issue-54302-cases.rs b/src/test/ui/issue-54302-cases.rs new file mode 100644 index 000000000000..6d1c61c80f06 --- /dev/null +++ b/src/test/ui/issue-54302-cases.rs @@ -0,0 +1,95 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Mirror { + type Image; + fn coerce(self) -> Self::Image; +} + +impl Mirror for T { + type Image = T; + fn coerce(self) -> Self { self } +} + +trait Foo<'x, T> { + fn foo(self) -> &'x T; +} + +impl<'s, 'x, T: 'x> Foo<'x, T> for &'s T where &'s T: Foo2<'x, T> { + fn foo(self) -> &'x T { self.foo2() } +} + +trait Foo2<'x, T> { + fn foo2(self) -> &'x T; +} + +// example 1 - fails leak check +impl<'x> Foo2<'x, u32> for &'x u32 +{ + fn foo2(self) -> &'x u32 { self } +} + +// example 2 - OK with this issue +impl<'x, 'a: 'x> Foo2<'x, i32> for &'a i32 +{ + fn foo2(self) -> &'x i32 { self } +} + +// example 3 - fails due to issue #XYZ + Leak-check +impl<'x, T> Foo2<'x, u64> for T + where T: Mirror +{ + fn foo2(self) -> &'x u64 { self.coerce() } +} + +// example 4 - fails due to issue #XYZ +impl<'x, 'a: 'x, T> Foo2<'x, i64> for T + where T: Mirror +{ + fn foo2(self) -> &'x i64 { self.coerce() } +} + + +trait RefFoo { + fn ref_foo(&self) -> &'static T; +} + +impl RefFoo for T where for<'a> &'a T: Foo<'static, T> { + fn ref_foo(&self) -> &'static T { + self.foo() + } +} + + +fn coerce_lifetime1(a: &u32) -> &'static u32 +{ + >::ref_foo(a) + //~^ ERROR the trait bound `for<'a> &'a u32: Foo2<'_, u32>` is not satisfied +} + +fn coerce_lifetime2(a: &i32) -> &'static i32 +{ + >::ref_foo(a) + //~^ ERROR the requirement `for<'a> 'a : ` is not satisfied +} + +fn coerce_lifetime3(a: &u64) -> &'static u64 +{ + >::ref_foo(a) + //~^ ERROR type mismatch resolving `for<'a> <&'a u64 as Mirror>::Image == &u64` +} + +fn coerce_lifetime4(a: &i64) -> &'static i64 +{ + >::ref_foo(a) + //~^ ERROR type mismatch resolving `for<'a> <&'a i64 as Mirror>::Image == &i64` +} + +fn main() {} diff --git a/src/test/ui/issue-54302-cases.stderr b/src/test/ui/issue-54302-cases.stderr new file mode 100644 index 000000000000..9603f7a973c1 --- /dev/null +++ b/src/test/ui/issue-54302-cases.stderr @@ -0,0 +1,65 @@ +error[E0277]: the trait bound `for<'a> &'a u32: Foo2<'_, u32>` is not satisfied + --> $DIR/issue-54302-cases.rs:73:5 + | +LL | >::ref_foo(a) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Foo2<'_, u32>` is not implemented for `&'a u32` + | + = help: the following implementations were found: + <&'x u32 as Foo2<'x, u32>> + = note: required because of the requirements on the impl of `for<'a> Foo<'static, u32>` for `&'a u32` + = note: required because of the requirements on the impl of `RefFoo` for `u32` +note: required by `RefFoo::ref_foo` + --> $DIR/issue-54302-cases.rs:61:5 + | +LL | fn ref_foo(&self) -> &'static T; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0279]: the requirement `for<'a> 'a : ` is not satisfied (`expected bound lifetime parameter 'a, found concrete lifetime`) + --> $DIR/issue-54302-cases.rs:79:5 + | +LL | >::ref_foo(a) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: required because of the requirements on the impl of `for<'a> Foo2<'_, i32>` for `&'a i32` + = note: required because of the requirements on the impl of `for<'a> Foo<'static, i32>` for `&'a i32` + = note: required because of the requirements on the impl of `RefFoo` for `i32` +note: required by `RefFoo::ref_foo` + --> $DIR/issue-54302-cases.rs:61:5 + | +LL | fn ref_foo(&self) -> &'static T; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0271]: type mismatch resolving `for<'a> <&'a u64 as Mirror>::Image == &u64` + --> $DIR/issue-54302-cases.rs:85:5 + | +LL | >::ref_foo(a) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'a, found concrete lifetime + | + = note: required because of the requirements on the impl of `for<'a> Foo2<'_, u64>` for `&'a u64` + = note: required because of the requirements on the impl of `for<'a> Foo<'static, u64>` for `&'a u64` + = note: required because of the requirements on the impl of `RefFoo` for `u64` +note: required by `RefFoo::ref_foo` + --> $DIR/issue-54302-cases.rs:61:5 + | +LL | fn ref_foo(&self) -> &'static T; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0271]: type mismatch resolving `for<'a> <&'a i64 as Mirror>::Image == &i64` + --> $DIR/issue-54302-cases.rs:91:5 + | +LL | >::ref_foo(a) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'a, found concrete lifetime + | + = note: required because of the requirements on the impl of `for<'a> Foo2<'_, i64>` for `&'a i64` + = note: required because of the requirements on the impl of `for<'a> Foo<'static, i64>` for `&'a i64` + = note: required because of the requirements on the impl of `RefFoo` for `i64` +note: required by `RefFoo::ref_foo` + --> $DIR/issue-54302-cases.rs:61:5 + | +LL | fn ref_foo(&self) -> &'static T; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + +Some errors occurred: E0271, E0277, E0279. +For more information about an error, try `rustc --explain E0271`. diff --git a/src/test/ui/issue-54302.rs b/src/test/ui/issue-54302.rs new file mode 100644 index 000000000000..969d19cac2d7 --- /dev/null +++ b/src/test/ui/issue-54302.rs @@ -0,0 +1,29 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Deserialize<'de> {} + +trait DeserializeOwned: for<'de> Deserialize<'de> {} +impl DeserializeOwned for T where T: for<'de> Deserialize<'de> {} + +// Based on this impl, `&'static str` only implements Deserialize<'static>. +// It does not implement for<'de> Deserialize<'de>. +impl<'de: 'a, 'a> Deserialize<'de> for &'a str {} + +fn main() { + // Then why does it implement DeserializeOwned? This compiles. + fn assert_deserialize_owned() {} + assert_deserialize_owned::<&'static str>(); + //~^ ERROR the requirement `for<'de> 'de : ` is not satisfied + + // It correctly does not implement for<'de> Deserialize<'de>. + //fn assert_hrtb Deserialize<'de>>() {} + //assert_hrtb::<&'static str>(); +} diff --git a/src/test/ui/issue-54302.stderr b/src/test/ui/issue-54302.stderr new file mode 100644 index 000000000000..f122daeecf63 --- /dev/null +++ b/src/test/ui/issue-54302.stderr @@ -0,0 +1,17 @@ +error[E0279]: the requirement `for<'de> 'de : ` is not satisfied (`expected bound lifetime parameter 'de, found concrete lifetime`) + --> $DIR/issue-54302.rs:23:5 + | +LL | assert_deserialize_owned::<&'static str>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: required because of the requirements on the impl of `for<'de> Deserialize<'de>` for `&'static str` + = note: required because of the requirements on the impl of `DeserializeOwned` for `&'static str` +note: required by `main::assert_deserialize_owned` + --> $DIR/issue-54302.rs:22:5 + | +LL | fn assert_deserialize_owned() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0279`. diff --git a/src/test/ui/range/issue-54505-no-literals.fixed b/src/test/ui/range/issue-54505-no-literals.fixed new file mode 100644 index 000000000000..4d8f67182b9a --- /dev/null +++ b/src/test/ui/range/issue-54505-no-literals.fixed @@ -0,0 +1,75 @@ +// run-rustfix + +// Regression test for changes introduced while fixing #54505 + +// This test uses non-literals for Ranges +// (expecting no parens with borrow suggestion) + +use std::ops::RangeBounds; + + +// take a reference to any built-in range +fn take_range(_r: &impl RangeBounds) {} + + +fn main() { + take_range(&std::ops::Range { start: 0, end: 1 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &std::ops::Range { start: 0, end: 1 } + + take_range(&::std::ops::Range { start: 0, end: 1 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &::std::ops::Range { start: 0, end: 1 } + + take_range(&std::ops::RangeFrom { start: 1 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &std::ops::RangeFrom { start: 1 } + + take_range(&::std::ops::RangeFrom { start: 1 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &::std::ops::RangeFrom { start: 1 } + + take_range(&std::ops::RangeFull {}); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &std::ops::RangeFull {} + + take_range(&::std::ops::RangeFull {}); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &::std::ops::RangeFull {} + + take_range(&std::ops::RangeInclusive::new(0, 1)); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &std::ops::RangeInclusive::new(0, 1) + + take_range(&::std::ops::RangeInclusive::new(0, 1)); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &::std::ops::RangeInclusive::new(0, 1) + + take_range(&std::ops::RangeTo { end: 5 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &std::ops::RangeTo { end: 5 } + + take_range(&::std::ops::RangeTo { end: 5 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &::std::ops::RangeTo { end: 5 } + + take_range(&std::ops::RangeToInclusive { end: 5 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &std::ops::RangeToInclusive { end: 5 } + + take_range(&::std::ops::RangeToInclusive { end: 5 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &::std::ops::RangeToInclusive { end: 5 } +} diff --git a/src/test/ui/range/issue-54505-no-literals.rs b/src/test/ui/range/issue-54505-no-literals.rs new file mode 100644 index 000000000000..dc21dcbc2db4 --- /dev/null +++ b/src/test/ui/range/issue-54505-no-literals.rs @@ -0,0 +1,75 @@ +// run-rustfix + +// Regression test for changes introduced while fixing #54505 + +// This test uses non-literals for Ranges +// (expecting no parens with borrow suggestion) + +use std::ops::RangeBounds; + + +// take a reference to any built-in range +fn take_range(_r: &impl RangeBounds) {} + + +fn main() { + take_range(std::ops::Range { start: 0, end: 1 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &std::ops::Range { start: 0, end: 1 } + + take_range(::std::ops::Range { start: 0, end: 1 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &::std::ops::Range { start: 0, end: 1 } + + take_range(std::ops::RangeFrom { start: 1 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &std::ops::RangeFrom { start: 1 } + + take_range(::std::ops::RangeFrom { start: 1 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &::std::ops::RangeFrom { start: 1 } + + take_range(std::ops::RangeFull {}); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &std::ops::RangeFull {} + + take_range(::std::ops::RangeFull {}); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &::std::ops::RangeFull {} + + take_range(std::ops::RangeInclusive::new(0, 1)); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &std::ops::RangeInclusive::new(0, 1) + + take_range(::std::ops::RangeInclusive::new(0, 1)); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &::std::ops::RangeInclusive::new(0, 1) + + take_range(std::ops::RangeTo { end: 5 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &std::ops::RangeTo { end: 5 } + + take_range(::std::ops::RangeTo { end: 5 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &::std::ops::RangeTo { end: 5 } + + take_range(std::ops::RangeToInclusive { end: 5 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &std::ops::RangeToInclusive { end: 5 } + + take_range(::std::ops::RangeToInclusive { end: 5 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &::std::ops::RangeToInclusive { end: 5 } +} diff --git a/src/test/ui/range/issue-54505-no-literals.stderr b/src/test/ui/range/issue-54505-no-literals.stderr new file mode 100644 index 000000000000..b8811c98d21b --- /dev/null +++ b/src/test/ui/range/issue-54505-no-literals.stderr @@ -0,0 +1,147 @@ +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:16:16 + | +LL | take_range(std::ops::Range { start: 0, end: 1 }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected reference, found struct `std::ops::Range` + | help: consider borrowing here: `&std::ops::Range { start: 0, end: 1 }` + | + = note: expected type `&_` + found type `std::ops::Range<{integer}>` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:21:16 + | +LL | take_range(::std::ops::Range { start: 0, end: 1 }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected reference, found struct `std::ops::Range` + | help: consider borrowing here: `&::std::ops::Range { start: 0, end: 1 }` + | + = note: expected type `&_` + found type `std::ops::Range<{integer}>` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:26:16 + | +LL | take_range(std::ops::RangeFrom { start: 1 }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected reference, found struct `std::ops::RangeFrom` + | help: consider borrowing here: `&std::ops::RangeFrom { start: 1 }` + | + = note: expected type `&_` + found type `std::ops::RangeFrom<{integer}>` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:31:16 + | +LL | take_range(::std::ops::RangeFrom { start: 1 }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected reference, found struct `std::ops::RangeFrom` + | help: consider borrowing here: `&::std::ops::RangeFrom { start: 1 }` + | + = note: expected type `&_` + found type `std::ops::RangeFrom<{integer}>` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:36:16 + | +LL | take_range(std::ops::RangeFull {}); + | ^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected reference, found struct `std::ops::RangeFull` + | help: consider borrowing here: `&std::ops::RangeFull {}` + | + = note: expected type `&_` + found type `std::ops::RangeFull` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:41:16 + | +LL | take_range(::std::ops::RangeFull {}); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected reference, found struct `std::ops::RangeFull` + | help: consider borrowing here: `&::std::ops::RangeFull {}` + | + = note: expected type `&_` + found type `std::ops::RangeFull` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:46:16 + | +LL | take_range(std::ops::RangeInclusive::new(0, 1)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected reference, found struct `std::ops::RangeInclusive` + | help: consider borrowing here: `&std::ops::RangeInclusive::new(0, 1)` + | + = note: expected type `&_` + found type `std::ops::RangeInclusive<{integer}>` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:51:16 + | +LL | take_range(::std::ops::RangeInclusive::new(0, 1)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected reference, found struct `std::ops::RangeInclusive` + | help: consider borrowing here: `&::std::ops::RangeInclusive::new(0, 1)` + | + = note: expected type `&_` + found type `std::ops::RangeInclusive<{integer}>` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:56:16 + | +LL | take_range(std::ops::RangeTo { end: 5 }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected reference, found struct `std::ops::RangeTo` + | help: consider borrowing here: `&std::ops::RangeTo { end: 5 }` + | + = note: expected type `&_` + found type `std::ops::RangeTo<{integer}>` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:61:16 + | +LL | take_range(::std::ops::RangeTo { end: 5 }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected reference, found struct `std::ops::RangeTo` + | help: consider borrowing here: `&::std::ops::RangeTo { end: 5 }` + | + = note: expected type `&_` + found type `std::ops::RangeTo<{integer}>` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:66:16 + | +LL | take_range(std::ops::RangeToInclusive { end: 5 }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected reference, found struct `std::ops::RangeToInclusive` + | help: consider borrowing here: `&std::ops::RangeToInclusive { end: 5 }` + | + = note: expected type `&_` + found type `std::ops::RangeToInclusive<{integer}>` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:71:16 + | +LL | take_range(::std::ops::RangeToInclusive { end: 5 }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected reference, found struct `std::ops::RangeToInclusive` + | help: consider borrowing here: `&::std::ops::RangeToInclusive { end: 5 }` + | + = note: expected type `&_` + found type `std::ops::RangeToInclusive<{integer}>` + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/range/issue-54505-no-std.rs b/src/test/ui/range/issue-54505-no-std.rs new file mode 100644 index 000000000000..c2b17b53ba16 --- /dev/null +++ b/src/test/ui/range/issue-54505-no-std.rs @@ -0,0 +1,50 @@ +// error-pattern: `#[panic_handler]` function required, but not found +// error-pattern: language item required, but not found: `eh_personality` + + +// Regression test for #54505 - range borrowing suggestion had +// incorrect syntax (missing parentheses). + +// This test doesn't use std +// (so all Ranges resolve to core::ops::Range...) + +#![no_std] + +use core::ops::RangeBounds; + + +// take a reference to any built-in range +fn take_range(_r: &impl RangeBounds) {} + + +fn main() { + take_range(0..1); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(0..1) + + take_range(1..); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(1..) + + take_range(..); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(..) + + take_range(0..=1); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(0..=1) + + take_range(..5); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(..5) + + take_range(..=42); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(..=42) +} diff --git a/src/test/ui/range/issue-54505-no-std.stderr b/src/test/ui/range/issue-54505-no-std.stderr new file mode 100644 index 000000000000..2810a3f076d4 --- /dev/null +++ b/src/test/ui/range/issue-54505-no-std.stderr @@ -0,0 +1,79 @@ +error: `#[panic_handler]` function required, but not found + +error: language item required, but not found: `eh_personality` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-std.rs:21:16 + | +LL | take_range(0..1); + | ^^^^ + | | + | expected reference, found struct `core::ops::Range` + | help: consider borrowing here: `&(0..1)` + | + = note: expected type `&_` + found type `core::ops::Range<{integer}>` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-std.rs:26:16 + | +LL | take_range(1..); + | ^^^ + | | + | expected reference, found struct `core::ops::RangeFrom` + | help: consider borrowing here: `&(1..)` + | + = note: expected type `&_` + found type `core::ops::RangeFrom<{integer}>` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-std.rs:31:16 + | +LL | take_range(..); + | ^^ + | | + | expected reference, found struct `core::ops::RangeFull` + | help: consider borrowing here: `&(..)` + | + = note: expected type `&_` + found type `core::ops::RangeFull` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-std.rs:36:16 + | +LL | take_range(0..=1); + | ^^^^^ + | | + | expected reference, found struct `core::ops::RangeInclusive` + | help: consider borrowing here: `&(0..=1)` + | + = note: expected type `&_` + found type `core::ops::RangeInclusive<{integer}>` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-std.rs:41:16 + | +LL | take_range(..5); + | ^^^ + | | + | expected reference, found struct `core::ops::RangeTo` + | help: consider borrowing here: `&(..5)` + | + = note: expected type `&_` + found type `core::ops::RangeTo<{integer}>` + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-std.rs:46:16 + | +LL | take_range(..=42); + | ^^^^^ + | | + | expected reference, found struct `core::ops::RangeToInclusive` + | help: consider borrowing here: `&(..=42)` + | + = note: expected type `&_` + found type `core::ops::RangeToInclusive<{integer}>` + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/range/issue-54505.fixed b/src/test/ui/range/issue-54505.fixed new file mode 100644 index 000000000000..f8298c0b5cef --- /dev/null +++ b/src/test/ui/range/issue-54505.fixed @@ -0,0 +1,43 @@ +// run-rustfix + +// Regression test for #54505 - range borrowing suggestion had +// incorrect syntax (missing parentheses). + +use std::ops::RangeBounds; + + +// take a reference to any built-in range +fn take_range(_r: &impl RangeBounds) {} + + +fn main() { + take_range(&(0..1)); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(0..1) + + take_range(&(1..)); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(1..) + + take_range(&(..)); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(..) + + take_range(&(0..=1)); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(0..=1) + + take_range(&(..5)); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(..5) + + take_range(&(..=42)); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(..=42) +} diff --git a/src/test/ui/range/issue-54505.rs b/src/test/ui/range/issue-54505.rs new file mode 100644 index 000000000000..03673252dd3b --- /dev/null +++ b/src/test/ui/range/issue-54505.rs @@ -0,0 +1,43 @@ +// run-rustfix + +// Regression test for #54505 - range borrowing suggestion had +// incorrect syntax (missing parentheses). + +use std::ops::RangeBounds; + + +// take a reference to any built-in range +fn take_range(_r: &impl RangeBounds) {} + + +fn main() { + take_range(0..1); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(0..1) + + take_range(1..); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(1..) + + take_range(..); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(..) + + take_range(0..=1); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(0..=1) + + take_range(..5); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(..5) + + take_range(..=42); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(..=42) +} diff --git a/src/test/ui/range/issue-54505.stderr b/src/test/ui/range/issue-54505.stderr new file mode 100644 index 000000000000..d6e1fb0cef23 --- /dev/null +++ b/src/test/ui/range/issue-54505.stderr @@ -0,0 +1,75 @@ +error[E0308]: mismatched types + --> $DIR/issue-54505.rs:14:16 + | +LL | take_range(0..1); + | ^^^^ + | | + | expected reference, found struct `std::ops::Range` + | help: consider borrowing here: `&(0..1)` + | + = note: expected type `&_` + found type `std::ops::Range<{integer}>` + +error[E0308]: mismatched types + --> $DIR/issue-54505.rs:19:16 + | +LL | take_range(1..); + | ^^^ + | | + | expected reference, found struct `std::ops::RangeFrom` + | help: consider borrowing here: `&(1..)` + | + = note: expected type `&_` + found type `std::ops::RangeFrom<{integer}>` + +error[E0308]: mismatched types + --> $DIR/issue-54505.rs:24:16 + | +LL | take_range(..); + | ^^ + | | + | expected reference, found struct `std::ops::RangeFull` + | help: consider borrowing here: `&(..)` + | + = note: expected type `&_` + found type `std::ops::RangeFull` + +error[E0308]: mismatched types + --> $DIR/issue-54505.rs:29:16 + | +LL | take_range(0..=1); + | ^^^^^ + | | + | expected reference, found struct `std::ops::RangeInclusive` + | help: consider borrowing here: `&(0..=1)` + | + = note: expected type `&_` + found type `std::ops::RangeInclusive<{integer}>` + +error[E0308]: mismatched types + --> $DIR/issue-54505.rs:34:16 + | +LL | take_range(..5); + | ^^^ + | | + | expected reference, found struct `std::ops::RangeTo` + | help: consider borrowing here: `&(..5)` + | + = note: expected type `&_` + found type `std::ops::RangeTo<{integer}>` + +error[E0308]: mismatched types + --> $DIR/issue-54505.rs:39:16 + | +LL | take_range(..=42); + | ^^^^^ + | | + | expected reference, found struct `std::ops::RangeToInclusive` + | help: consider borrowing here: `&(..=42)` + | + = note: expected type `&_` + found type `std::ops::RangeToInclusive<{integer}>` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/run-pass/traits/traits-static-outlives-a-where-clause.rs b/src/test/ui/run-pass/traits/traits-static-outlives-a-where-clause.rs new file mode 100644 index 000000000000..1051bec63079 --- /dev/null +++ b/src/test/ui/run-pass/traits/traits-static-outlives-a-where-clause.rs @@ -0,0 +1,33 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-pass + +trait Foo<'a> { + fn xyz(self); +} +impl<'a, T> Foo<'a> for T where 'static: 'a { + fn xyz(self) {} +} + +trait Bar { + fn uvw(self); +} +impl Bar for T where for<'a> T: Foo<'a> { + fn uvw(self) { self.xyz(); } +} + +fn foo(t: T) where T: Bar { + t.uvw(); +} + +fn main() { + foo(0); +}