Skip to content

Rollup of 7 pull requests #133152

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Nov 18, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 10 additions & 16 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
@@ -27,7 +27,7 @@ use rustc_middle::mir::{
};
use rustc_middle::ty::print::PrintTraitRefExt as _;
use rustc_middle::ty::{
self, ClauseKind, PredicateKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor, Upcast,
self, PredicateKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor, Upcast,
suggest_constraining_type_params,
};
use rustc_middle::util::CallKind;
@@ -649,11 +649,11 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
) -> Option<ty::Mutability> {
let tcx = self.infcx.tcx;
let sig = tcx.fn_sig(callee_did).instantiate_identity().skip_binder();
let clauses = tcx.predicates_of(callee_did).instantiate_identity(self.infcx.tcx).predicates;
let clauses = tcx.predicates_of(callee_did);

// First, is there at least one method on one of `param`'s trait bounds?
// This keeps us from suggesting borrowing the argument to `mem::drop`, e.g.
if !clauses.iter().any(|clause| {
if !clauses.instantiate_identity(tcx).predicates.iter().any(|clause| {
clause.as_trait_clause().is_some_and(|tc| {
tc.self_ty().skip_binder().is_param(param.index)
&& tc.polarity() == ty::PredicatePolarity::Positive
@@ -700,23 +700,17 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
return false;
}

// Test the callee's predicates, substituting a reference in for the self ty
// in bounds on `param`.
clauses.iter().all(|&clause| {
let clause_for_ref = clause.kind().map_bound(|kind| match kind {
ClauseKind::Trait(c) if c.self_ty().is_param(param.index) => {
ClauseKind::Trait(c.with_self_ty(tcx, ref_ty))
}
ClauseKind::Projection(c) if c.self_ty().is_param(param.index) => {
ClauseKind::Projection(c.with_self_ty(tcx, ref_ty))
}
_ => kind,
});
// Test the callee's predicates, substituting in `ref_ty` for the moved argument type.
clauses.instantiate(tcx, new_args).predicates.iter().all(|&(mut clause)| {
// Normalize before testing to see through type aliases and projections.
if let Ok(normalized) = tcx.try_normalize_erasing_regions(self.param_env, clause) {
clause = normalized;
}
self.infcx.predicate_must_hold_modulo_regions(&Obligation::new(
tcx,
ObligationCause::dummy(),
self.param_env,
ty::EarlyBinder::bind(clause_for_ref).instantiate(tcx, generic_args),
clause,
))
})
}) {
19 changes: 12 additions & 7 deletions compiler/rustc_feature/src/lib.rs
Original file line number Diff line number Diff line change
@@ -74,14 +74,19 @@ impl UnstableFeatures {
// Returns whether `krate` should be counted as unstable
let is_unstable_crate =
|var: &str| krate.is_some_and(|name| var.split(',').any(|new_krate| new_krate == name));
// `true` if we should enable unstable features for bootstrapping.
let bootstrap =
std::env::var("RUSTC_BOOTSTRAP").is_ok_and(|var| var == "1" || is_unstable_crate(&var));
match (disable_unstable_features, bootstrap) {
(_, true) => UnstableFeatures::Cheat,
(true, _) => UnstableFeatures::Disallow,
(false, _) => UnstableFeatures::Allow,

let bootstrap = std::env::var("RUSTC_BOOTSTRAP").ok();
if let Some(val) = bootstrap.as_deref() {
match val {
val if val == "1" || is_unstable_crate(val) => return UnstableFeatures::Cheat,
// Hypnotize ourselves so that we think we are a stable compiler and thus don't
// allow any unstable features.
"-1" => return UnstableFeatures::Disallow,
_ => {}
}
}

if disable_unstable_features { UnstableFeatures::Disallow } else { UnstableFeatures::Allow }
}

pub fn is_nightly_build(&self) -> bool {
12 changes: 11 additions & 1 deletion compiler/rustc_feature/src/tests.rs
Original file line number Diff line number Diff line change
@@ -18,6 +18,16 @@ fn rustc_bootstrap_parsing() {
assert!(!is_bootstrap("x,y,z", Some("a")));
assert!(!is_bootstrap("x,y,z", None));

// this is technically a breaking change, but there are no stability guarantees for RUSTC_BOOTSTRAP
// `RUSTC_BOOTSTRAP=0` is not recognized.
assert!(!is_bootstrap("0", None));

// `RUSTC_BOOTSTRAP=-1` is force-stable, no unstable features allowed.
let is_force_stable = |krate| {
std::env::set_var("RUSTC_BOOTSTRAP", "-1");
matches!(UnstableFeatures::from_environment(krate), UnstableFeatures::Disallow)
};
assert!(is_force_stable(None));
// Does not support specifying any crate.
assert!(is_force_stable(Some("x")));
assert!(is_force_stable(Some("x,y,z")));
}
2 changes: 1 addition & 1 deletion compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
@@ -54,7 +54,7 @@ pub struct EnabledLangFeature {
pub stable_since: Option<Symbol>,
}

/// Information abhout an enabled library feature.
/// Information about an enabled library feature.
#[derive(Debug, Copy, Clone)]
pub struct EnabledLibFeature {
pub gate_name: Symbol,
5 changes: 5 additions & 0 deletions compiler/rustc_hir_analysis/messages.ftl
Original file line number Diff line number Diff line change
@@ -448,6 +448,11 @@ hir_analysis_rpitit_refined = impl trait in impl method signature does not match
.note = add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate
.feedback_note = we are soliciting feedback, see issue #121718 <https://github.com/rust-lang/rust/issues/121718> for more information

hir_analysis_rpitit_refined_lifetimes = impl trait in impl method captures fewer lifetimes than in trait
.suggestion = modify the `use<..>` bound to capture the same lifetimes that the trait does
.note = add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate
.feedback_note = we are soliciting feedback, see issue #121718 <https://github.com/rust-lang/rust/issues/121718> for more information

hir_analysis_self_in_impl_self =
`Self` is not valid in the self type of an impl block
.note = replace `Self` with a different type
102 changes: 101 additions & 1 deletion compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use itertools::Itertools as _;
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_lint_defs::builtin::{REFINING_IMPL_TRAIT_INTERNAL, REFINING_IMPL_TRAIT_REACHABLE};
@@ -75,6 +76,8 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
let mut trait_bounds = vec![];
// Bounds that we find on the RPITITs in the impl signature.
let mut impl_bounds = vec![];
// Pairs of trait and impl opaques.
let mut pairs = vec![];

for trait_projection in collector.types.into_iter().rev() {
let impl_opaque_args = trait_projection.args.rebase_onto(tcx, trait_m.def_id, impl_m_args);
@@ -121,6 +124,8 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
tcx.explicit_item_bounds(impl_opaque.def_id)
.iter_instantiated_copied(tcx, impl_opaque.args),
));

pairs.push((trait_projection, impl_opaque));
}

let hybrid_preds = tcx
@@ -212,6 +217,39 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
return;
}
}

// Make sure that the RPITIT doesn't capture fewer regions than
// the trait definition. We hard-error if it captures *more*, since that
// is literally unrepresentable in the type system; however, we may be
// promising stronger outlives guarantees if we capture *fewer* regions.
for (trait_projection, impl_opaque) in pairs {
let impl_variances = tcx.variances_of(impl_opaque.def_id);
let impl_captures: FxIndexSet<_> = impl_opaque
.args
.iter()
.zip_eq(impl_variances)
.filter(|(_, v)| **v == ty::Invariant)
.map(|(arg, _)| arg)
.collect();

let trait_variances = tcx.variances_of(trait_projection.def_id);
let mut trait_captures = FxIndexSet::default();
for (arg, variance) in trait_projection.args.iter().zip_eq(trait_variances) {
if *variance != ty::Invariant {
continue;
}
arg.visit_with(&mut CollectParams { params: &mut trait_captures });
}

if !trait_captures.iter().all(|arg| impl_captures.contains(arg)) {
report_mismatched_rpitit_captures(
tcx,
impl_opaque.def_id.expect_local(),
trait_captures,
is_internal,
);
}
}
}

struct ImplTraitInTraitCollector<'tcx> {
@@ -342,3 +380,65 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Anonymize<'tcx> {
self.tcx.anonymize_bound_vars(t)
}
}

struct CollectParams<'a, 'tcx> {
params: &'a mut FxIndexSet<ty::GenericArg<'tcx>>,
}
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for CollectParams<'_, 'tcx> {
fn visit_ty(&mut self, ty: Ty<'tcx>) {
if let ty::Param(_) = ty.kind() {
self.params.insert(ty.into());
} else {
ty.super_visit_with(self);
}
}
fn visit_region(&mut self, r: ty::Region<'tcx>) {
match r.kind() {
ty::ReEarlyParam(_) | ty::ReLateParam(_) => {
self.params.insert(r.into());
}
_ => {}
}
}
fn visit_const(&mut self, ct: ty::Const<'tcx>) {
if let ty::ConstKind::Param(_) = ct.kind() {
self.params.insert(ct.into());
} else {
ct.super_visit_with(self);
}
}
}

fn report_mismatched_rpitit_captures<'tcx>(
tcx: TyCtxt<'tcx>,
impl_opaque_def_id: LocalDefId,
mut trait_captured_args: FxIndexSet<ty::GenericArg<'tcx>>,
is_internal: bool,
) {
let Some(use_bound_span) =
tcx.hir_node_by_def_id(impl_opaque_def_id).expect_opaque_ty().bounds.iter().find_map(
|bound| match *bound {
rustc_hir::GenericBound::Use(_, span) => Some(span),
hir::GenericBound::Trait(_) | hir::GenericBound::Outlives(_) => None,
},
)
else {
// I have no idea when you would ever undercapture without a `use<..>`.
tcx.dcx().delayed_bug("expected use<..> to undercapture in an impl opaque");
return;
};

trait_captured_args
.sort_by_cached_key(|arg| !matches!(arg.unpack(), ty::GenericArgKind::Lifetime(_)));
let suggestion = format!("use<{}>", trait_captured_args.iter().join(", "));

tcx.emit_node_span_lint(
if is_internal { REFINING_IMPL_TRAIT_INTERNAL } else { REFINING_IMPL_TRAIT_REACHABLE },
tcx.local_def_id_to_hir_id(impl_opaque_def_id),
use_bound_span,
crate::errors::ReturnPositionImplTraitInTraitRefinedLifetimes {
suggestion_span: use_bound_span,
suggestion,
},
);
}
10 changes: 10 additions & 0 deletions compiler/rustc_hir_analysis/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1153,6 +1153,16 @@ pub(crate) struct ReturnPositionImplTraitInTraitRefined<'tcx> {
pub return_ty: Ty<'tcx>,
}

#[derive(LintDiagnostic)]
#[diag(hir_analysis_rpitit_refined_lifetimes)]
#[note]
#[note(hir_analysis_feedback_note)]
pub(crate) struct ReturnPositionImplTraitInTraitRefinedLifetimes {
#[suggestion(applicability = "maybe-incorrect", code = "{suggestion}")]
pub suggestion_span: Span,
pub suggestion: String,
}

#[derive(Diagnostic)]
#[diag(hir_analysis_inherent_ty_outside, code = E0390)]
#[help]
33 changes: 24 additions & 9 deletions compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
Original file line number Diff line number Diff line change
@@ -2648,15 +2648,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}

let make_sugg = |expr: &Expr<'_>, span: Span, sugg: &str| {
let needs_parens = match expr.kind {
// parenthesize if needed (Issue #46756)
hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true,
// parenthesize borrows of range literals (Issue #54505)
_ if is_range_literal(expr) => true,
_ => false,
};

if needs_parens {
if self.needs_parentheses(expr) {
(
vec![
(span.shrink_to_lo(), format!("{prefix}{sugg}(")),
@@ -2869,6 +2861,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return None;
}

if self.needs_parentheses(expr) {
return Some((
vec![
(span, format!("{suggestion}(")),
(expr.span.shrink_to_hi(), ")".to_string()),
],
message,
Applicability::MachineApplicable,
true,
false,
));
}

return Some((
vec![(span, suggestion)],
message,
@@ -2897,6 +2902,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
false
}

fn needs_parentheses(&self, expr: &hir::Expr<'_>) -> bool {
match expr.kind {
// parenthesize if needed (Issue #46756)
hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true,
// parenthesize borrows of range literals (Issue #54505)
_ if is_range_literal(expr) => true,
_ => false,
}
}

pub(crate) fn suggest_cast(
&self,
err: &mut Diag<'_>,
33 changes: 25 additions & 8 deletions compiler/rustc_parse/src/parser/item.rs
Original file line number Diff line number Diff line change
@@ -77,18 +77,35 @@ impl<'a> Parser<'a> {
if !self.eat(term) {
let token_str = super::token_descr(&self.token);
if !self.maybe_consume_incorrect_semicolon(items.last().map(|x| &**x)) {
let is_let = self.token.is_keyword(kw::Let);
let is_let_mut = is_let && self.look_ahead(1, |t| t.is_keyword(kw::Mut));
let let_has_ident = is_let && !is_let_mut && self.is_kw_followed_by_ident(kw::Let);

let msg = format!("expected item, found {token_str}");
let mut err = self.dcx().struct_span_err(self.token.span, msg);
let span = self.token.span;
if self.is_kw_followed_by_ident(kw::Let) {
err.span_label(
span,
"consider using `const` or `static` instead of `let` for global variables",
);

let label = if is_let {
"`let` cannot be used for global variables"
} else {
err.span_label(span, "expected item")
.note("for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>");
"expected item"
};
err.span_label(self.token.span, label);

if is_let {
if is_let_mut {
err.help("consider using `static` and a `Mutex` instead of `let mut`");
} else if let_has_ident {
err.span_suggestion_short(
self.token.span,
"consider using `static` or `const` instead of `let`",
"static",
Applicability::MaybeIncorrect,
);
} else {
err.help("consider using `static` or `const` instead of `let`");
}
}
err.note("for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>");
return Err(err);
}
}
2 changes: 1 addition & 1 deletion tests/incremental/hygiene/load_cached_hygiene.rs
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@
// This causes hygiene information to be saved to the incr cache.
// 2. One function is the foreign crate is modified. This causes the
// optimized mir for an unmodified function to be loaded from the
//@ incremental cache and written out to the crate metadata.
// incremental cache and written out to the crate metadata.
// 3. In the process of loading and writing out this function's MIR,
// we load hygiene information from the incremental cache and
// write it to our metadata.
7 changes: 7 additions & 0 deletions tests/rustdoc-js/trailing.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// exact-check
const EXPECTED = {
'query': 'inner::',
'others': [
{ 'path': 'trailing::inner', 'name': 'function' },
],
}
3 changes: 3 additions & 0 deletions tests/rustdoc-js/trailing.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod inner {
pub fn function() {}
}
10 changes: 10 additions & 0 deletions tests/ui/bootstrap/rustc_bootstap.force_stable.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
error: the option `Z` is only accepted on the nightly compiler

help: consider switching to a nightly toolchain: `rustup default nightly`

note: selecting a toolchain with `+toolchain` arguments require a rustup proxy; see <https://rust-lang.github.io/rustup/concepts/index.html>

note: for more information about Rust's stability policy, see <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html#unstable-features>

error: 1 nightly option were parsed

47 changes: 47 additions & 0 deletions tests/ui/bootstrap/rustc_bootstap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//! Check `RUSTC_BOOTSTRAP`'s behavior in relation to feature stability and what rustc considers
//! itself to be (stable vs non-stable ).
//!
//! `RUSTC_BOOTSTRAP` accepts:
//!
//! - `1`: cheat, allow usage of unstable features even if rustc thinks it is a stable compiler.
//! - `x,y,z`: comma-delimited list of crates.
//! - `-1`: force rustc to think it is a stable compiler.
// ignore-tidy-linelength

//@ revisions: default_nightly cheat cheat_single_crate cheat_multi_crate force_stable invalid_zero invalid_junk
//@ only-nightly

//@[default_nightly] unset-rustc-env:RUSTC_BOOTSTRAP
//@[default_nightly] check-pass

// For a nightly compiler, this is same as `default_nightly` as if `RUSTC_BOOTSTRAP` was unset.
//@[invalid_zero] rustc-env:RUSTC_BOOTSTRAP=0
//@[invalid_zero] check-pass

// Invalid values are silently discarded, same as `default_nightly`, i.e. as if `RUSTC_BOOTSTRAP`
// was unset.
//@[invalid_junk] rustc-env:RUSTC_BOOTSTRAP=*
//@[invalid_junk] check-pass

//@[cheat] rustc-env:RUSTC_BOOTSTRAP=1
//@[cheat] check-pass

//@[cheat_single_crate] rustc-env:RUSTC_BOOTSTRAP=x
//@[cheat_single_crate] check-pass

//@[cheat_multi_crate] rustc-env:RUSTC_BOOTSTRAP=x,y,z
//@[cheat_multi_crate] check-pass

// Note: compiletest passes some `-Z` flags to the compiler for ui testing purposes, so here we
// instead abuse the fact that `-Z unstable-options` is also part of rustc's stability story and is
// also affected by `RUSTC_BOOTSTRAP`.
//@[force_stable] rustc-env:RUSTC_BOOTSTRAP=-1
//@[force_stable] compile-flags: -Z unstable-options
//@[force_stable] regex-error-pattern: error: the option `Z` is only accepted on the nightly compiler

#![crate_type = "lib"]

// Note: `rustc_attrs` is a perma-unstable internal feature that is unlikely to change, which is
// used as a proxy to check `RUSTC_BOOTSTRAP` versus stability checking logic.
#![feature(rustc_attrs)]
18 changes: 18 additions & 0 deletions tests/ui/coercion/unboxing-needing-parenthases-issue-132924.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//@ check-fail
fn main() {
let x = Box::new(Some(1));

let test: Option<i32> = x;
//~^ ERROR mismatched types
let x = Box::new(Some(1));
let test: Option<i32> = { x as Box<Option<i32>> };
//~^ ERROR mismatched types

let x = Box::new(Some(1));
let test: Option<i32> = if true { x as Box<Option<i32>> } else { None };
//~^ ERROR mismatched types

let x = std::rc::Rc::new(Some(1));
let test: Option<i32> = x as std::rc::Rc<Option<i32>>;
//~^ ERROR mismatched types
}
59 changes: 59 additions & 0 deletions tests/ui/coercion/unboxing-needing-parenthases-issue-132924.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
error[E0308]: mismatched types
--> $DIR/unboxing-needing-parenthases-issue-132924.rs:5:29
|
LL | let test: Option<i32> = x;
| ----------- ^ expected `Option<i32>`, found `Box<Option<{integer}>>`
| |
| expected due to this
|
= note: expected enum `Option<i32>`
found struct `Box<Option<{integer}>>`
help: consider unboxing the value
|
LL | let test: Option<i32> = *x;
| +

error[E0308]: mismatched types
--> $DIR/unboxing-needing-parenthases-issue-132924.rs:8:31
|
LL | let test: Option<i32> = { x as Box<Option<i32>> };
| ^^^^^^^^^^^^^^^^^^^^^ expected `Option<i32>`, found `Box<Option<i32>>`
|
= note: expected enum `Option<_>`
found struct `Box<Option<_>>`
help: consider unboxing the value
|
LL | let test: Option<i32> = { *(x as Box<Option<i32>>) };
| ++ +

error[E0308]: mismatched types
--> $DIR/unboxing-needing-parenthases-issue-132924.rs:12:39
|
LL | let test: Option<i32> = if true { x as Box<Option<i32>> } else { None };
| ^^^^^^^^^^^^^^^^^^^^^ expected `Option<i32>`, found `Box<Option<i32>>`
|
= note: expected enum `Option<_>`
found struct `Box<Option<_>>`
help: consider unboxing the value
|
LL | let test: Option<i32> = if true { *(x as Box<Option<i32>>) } else { None };
| ++ +

error[E0308]: mismatched types
--> $DIR/unboxing-needing-parenthases-issue-132924.rs:16:29
|
LL | let test: Option<i32> = x as std::rc::Rc<Option<i32>>;
| ----------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Option<i32>`, found `Rc<Option<i32>>`
| |
| expected due to this
|
= note: expected enum `Option<_>`
found struct `Rc<Option<_>>`
help: consider dereferencing the type
|
LL | let test: Option<i32> = *(x as std::rc::Rc<Option<i32>>);
| ++ +

error: aborting due to 4 previous errors

For more information about this error, try `rustc --explain E0308`.
36 changes: 36 additions & 0 deletions tests/ui/impl-trait/in-trait/refine-captures.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#![feature(precise_capturing_in_traits)]

trait LifetimeParam<'a> {
fn test() -> impl Sized;
}
// Refining via capturing fewer lifetimes than the trait definition.
impl<'a> LifetimeParam<'a> for i32 {
fn test() -> impl Sized + use<> {}
//~^ WARN impl trait in impl method captures fewer lifetimes than in trait
}
// If the lifetime is substituted, then we don't refine anything.
impl LifetimeParam<'static> for u32 {
fn test() -> impl Sized + use<> {}
// Ok
}

trait TypeParam<T> {
fn test() -> impl Sized;
}
// Indirectly capturing a lifetime param through a type param substitution.
impl<'a> TypeParam<&'a ()> for i32 {
fn test() -> impl Sized + use<> {}
//~^ WARN impl trait in impl method captures fewer lifetimes than in trait
}
// Two of them, but only one is captured...
impl<'a, 'b> TypeParam<(&'a (), &'b ())> for u32 {
fn test() -> impl Sized + use<'b> {}
//~^ WARN impl trait in impl method captures fewer lifetimes than in trait
}
// What if we don't capture a type param? That should be an error otherwise.
impl<T> TypeParam<T> for u64 {
fn test() -> impl Sized + use<> {}
//~^ ERROR `impl Trait` must mention all type parameters in scope in `use<...>`
}

fn main() {}
52 changes: 52 additions & 0 deletions tests/ui/impl-trait/in-trait/refine-captures.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
warning: impl trait in impl method captures fewer lifetimes than in trait
--> $DIR/refine-captures.rs:8:31
|
LL | fn test() -> impl Sized + use<> {}
| ^^^^^
|
= note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate
= note: we are soliciting feedback, see issue #121718 <https://github.com/rust-lang/rust/issues/121718> for more information
= note: `#[warn(refining_impl_trait_internal)]` on by default
help: modify the `use<..>` bound to capture the same lifetimes that the trait does
|
LL | fn test() -> impl Sized + use<'a> {}
| ~~~~~~~

warning: impl trait in impl method captures fewer lifetimes than in trait
--> $DIR/refine-captures.rs:22:31
|
LL | fn test() -> impl Sized + use<> {}
| ^^^^^
|
= note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate
= note: we are soliciting feedback, see issue #121718 <https://github.com/rust-lang/rust/issues/121718> for more information
help: modify the `use<..>` bound to capture the same lifetimes that the trait does
|
LL | fn test() -> impl Sized + use<'a> {}
| ~~~~~~~

warning: impl trait in impl method captures fewer lifetimes than in trait
--> $DIR/refine-captures.rs:27:31
|
LL | fn test() -> impl Sized + use<'b> {}
| ^^^^^^^
|
= note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate
= note: we are soliciting feedback, see issue #121718 <https://github.com/rust-lang/rust/issues/121718> for more information
help: modify the `use<..>` bound to capture the same lifetimes that the trait does
|
LL | fn test() -> impl Sized + use<'a, 'b> {}
| ~~~~~~~~~~~

error: `impl Trait` must mention all type parameters in scope in `use<...>`
--> $DIR/refine-captures.rs:32:18
|
LL | impl<T> TypeParam<T> for u64 {
| - type parameter is implicitly captured by this `impl Trait`
LL | fn test() -> impl Sized + use<> {}
| ^^^^^^^^^^^^^^^^^^
|
= note: currently, all type parameters are required to be mentioned in the precise captures list

error: aborting due to 1 previous error; 3 warnings emitted

4 changes: 2 additions & 2 deletions tests/ui/moves/moved-value-on-as-ref-arg.fixed
Original file line number Diff line number Diff line change
@@ -18,8 +18,8 @@ impl AsMut<Bar> for Bar {

fn foo<T: AsRef<Bar>>(_: T) {}
fn qux<T: AsMut<Bar>>(_: T) {}
fn bat<T: Borrow<T>>(_: T) {}
fn baz<T: BorrowMut<T>>(_: T) {}
fn bat<T: Borrow<Bar>>(_: T) {}
fn baz<T: BorrowMut<Bar>>(_: T) {}

pub fn main() {
let bar = Bar;
4 changes: 2 additions & 2 deletions tests/ui/moves/moved-value-on-as-ref-arg.rs
Original file line number Diff line number Diff line change
@@ -18,8 +18,8 @@ impl AsMut<Bar> for Bar {

fn foo<T: AsRef<Bar>>(_: T) {}
fn qux<T: AsMut<Bar>>(_: T) {}
fn bat<T: Borrow<T>>(_: T) {}
fn baz<T: BorrowMut<T>>(_: T) {}
fn bat<T: Borrow<Bar>>(_: T) {}
fn baz<T: BorrowMut<Bar>>(_: T) {}

pub fn main() {
let bar = Bar;
25 changes: 25 additions & 0 deletions tests/ui/moves/region-var-in-moved-ty-issue-133118.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//! regression test for #133118
pub trait Alpha {
fn y(self) -> usize;
}

pub trait Beta {
type Gamma;
fn gamma(&self) -> Self::Gamma;
}

pub fn a<T: Alpha>(_x: T) -> usize {
todo!();
}

pub fn x<B>(beta: &B) -> usize
where
for<'a> &'a B: Beta,
for<'a> <&'a B as Beta>::Gamma: Alpha,
{
let g1 = beta.gamma();
a(g1) + a(g1) //~ ERROR use of moved value: `g1` [E0382]
}

pub fn main() {}
21 changes: 21 additions & 0 deletions tests/ui/moves/region-var-in-moved-ty-issue-133118.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
error[E0382]: use of moved value: `g1`
--> $DIR/region-var-in-moved-ty-issue-133118.rs:22:15
|
LL | let g1 = beta.gamma();
| -- move occurs because `g1` has type `<&B as Beta>::Gamma`, which does not implement the `Copy` trait
LL | a(g1) + a(g1)
| -- ^^ value used here after move
| |
| value moved here
|
note: consider changing this parameter type in function `a` to borrow instead if owning the value isn't necessary
--> $DIR/region-var-in-moved-ty-issue-133118.rs:12:24
|
LL | pub fn a<T: Alpha>(_x: T) -> usize {
| - ^ this parameter takes ownership of the value
| |
| in this function

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0382`.
7 changes: 6 additions & 1 deletion tests/ui/parser/suggest-const-for-global-var.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,12 @@ error: expected item, found keyword `let`
--> $DIR/suggest-const-for-global-var.rs:1:1
|
LL | let X: i32 = 12;
| ^^^ consider using `const` or `static` instead of `let` for global variables
| ^^^
| |
| `let` cannot be used for global variables
| help: consider using `static` or `const` instead of `let`
|
= note: for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>

error: aborting due to 1 previous error

5 changes: 5 additions & 0 deletions tests/ui/parser/suggest-static-for-global-var-mut.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
let mut _data = vec![1,2,3];
//~^ ERROR expected item, found keyword `let`

fn main() {
}
11 changes: 11 additions & 0 deletions tests/ui/parser/suggest-static-for-global-var-mut.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
error: expected item, found keyword `let`
--> $DIR/suggest-static-for-global-var-mut.rs:1:1
|
LL | let mut _data = vec![1,2,3];
| ^^^ `let` cannot be used for global variables
|
= help: consider using `static` and a `Mutex` instead of `let mut`
= note: for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>

error: aborting due to 1 previous error

2 changes: 1 addition & 1 deletion tests/ui/symbol-names/basic.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//@ build-fail
//@ revisions: legacy v0
//@[legacy]compile-flags: -Z unstable-options -C symbol-mangling-version=legacy
//@[v0]compile-flags: -C symbol-mangling-version=v0
//@[v0]compile-flags: -C symbol-mangling-version=v0

#![feature(rustc_attrs)]

2 changes: 1 addition & 1 deletion tests/ui/symbol-names/impl1.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//@ build-fail
//@ revisions: legacy v0
//@[legacy]compile-flags: -Z unstable-options -C symbol-mangling-version=legacy
//@[v0]compile-flags: -C symbol-mangling-version=v0
//@[v0]compile-flags: -C symbol-mangling-version=v0
//@[legacy]normalize-stderr-test: "h[\w]{16}E?\)" -> "<SYMBOL_HASH>)"

#![feature(auto_traits, rustc_attrs)]
2 changes: 1 addition & 1 deletion tests/ui/symbol-names/issue-60925.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//@ build-fail
//@ revisions: legacy v0
//@[legacy]compile-flags: -Z unstable-options -C symbol-mangling-version=legacy
//@[v0]compile-flags: -C symbol-mangling-version=v0
//@[v0]compile-flags: -C symbol-mangling-version=v0

#![feature(rustc_attrs)]