Skip to content

Commit f11ef80

Browse files
committed
Auto merge of rust-lang#126642 - GuillaumeGomez:rollup-ofclymo, r=GuillaumeGomez
Rollup of 9 pull requests Successful merges: - rust-lang#123782 (Test that opaque types can't have themselves as a hidden type with incompatible lifetimes) - rust-lang#124580 (Suggest removing unused tuple fields if they are the last fields) - rust-lang#125852 (improve tip for inaccessible traits) - rust-lang#126422 (Suggest using a standalone doctest for non-local impl defs) - rust-lang#126427 (Rewrite `intrinsic-unreachable`, `sepcomp-cci-copies`, `sepcomp-inlining` and `sepcomp-separate` `run-make` tests to rmake.rs) - rust-lang#126493 (safe transmute: support non-ZST, variantful, uninhabited enums) - rust-lang#126572 (override user defined channel when using precompiled rustc) - rust-lang#126615 (Add `rustc-ice*` to `.gitignore`) - rust-lang#126632 (Replace `move||` with `move ||`) Failed merges: - rust-lang#126558 (hir_typeck: be more conservative in making "note caller chooses ty param" note) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 8fcd4dd + ef8c24a commit f11ef80

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+724
-276
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ build/
5252
/src/tools/x/target
5353
# Created by default with `src/ci/docker/run.sh`
5454
/obj/
55+
/rustc-ice*
5556

5657
## Temporary files
5758
*~

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -3476,6 +3476,7 @@ dependencies = [
34763476
"object 0.34.0",
34773477
"regex",
34783478
"similar",
3479+
"walkdir",
34793480
"wasmparser",
34803481
]
34813482

compiler/rustc_const_eval/src/interpret/discriminant.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,16 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
241241
variant_index: VariantIdx,
242242
) -> InterpResult<'tcx, Option<(ScalarInt, usize)>> {
243243
match self.layout_of(ty)?.variants {
244-
abi::Variants::Single { .. } => Ok(None),
244+
abi::Variants::Single { .. } => {
245+
// The tag of a `Single` enum is like the tag of the niched
246+
// variant: there's no tag as the discriminant is encoded
247+
// entirely implicitly. If `write_discriminant` ever hits this
248+
// case, we do a "validation read" to ensure the the right
249+
// discriminant is encoded implicitly, so any attempt to write
250+
// the wrong discriminant for a `Single` enum will reliably
251+
// result in UB.
252+
Ok(None)
253+
}
245254

246255
abi::Variants::Multiple {
247256
tag_encoding: TagEncoding::Direct,

compiler/rustc_hir_typeck/src/method/suggest.rs

+140-45
Original file line numberDiff line numberDiff line change
@@ -303,14 +303,57 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
303303
}
304304
if !candidates.is_empty() {
305305
let help = format!(
306-
"{an}other candidate{s} {were} found in the following trait{s}, perhaps \
307-
add a `use` for {one_of_them}:",
306+
"{an}other candidate{s} {were} found in the following trait{s}",
308307
an = if candidates.len() == 1 { "an" } else { "" },
309308
s = pluralize!(candidates.len()),
310309
were = pluralize!("was", candidates.len()),
311-
one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
312310
);
313-
self.suggest_use_candidates(&mut err, help, candidates);
311+
self.suggest_use_candidates(
312+
candidates,
313+
|accessible_sugg, inaccessible_sugg, span| {
314+
let suggest_for_access =
315+
|err: &mut Diag<'_>, mut msg: String, sugg: Vec<_>| {
316+
msg += &format!(
317+
", perhaps add a `use` for {one_of_them}:",
318+
one_of_them =
319+
if sugg.len() == 1 { "it" } else { "one_of_them" },
320+
);
321+
err.span_suggestions(
322+
span,
323+
msg,
324+
sugg,
325+
Applicability::MaybeIncorrect,
326+
);
327+
};
328+
let suggest_for_privacy =
329+
|err: &mut Diag<'_>, mut msg: String, sugg: Vec<String>| {
330+
if sugg.len() == 1 {
331+
let msg = format!("\
332+
trait `{}` provides `{item_name}` is implemented but not reachable",
333+
sugg[0].trim()
334+
);
335+
err.help(msg);
336+
} else {
337+
msg += &format!(" but {} not reachable", pluralize!("is", sugg.len()));
338+
err.span_suggestions(
339+
span,
340+
msg,
341+
sugg,
342+
Applicability::MaybeIncorrect,
343+
);
344+
}
345+
};
346+
if accessible_sugg.is_empty() {
347+
// `inaccessible_sugg` must not be empty
348+
suggest_for_privacy(&mut err, help, inaccessible_sugg);
349+
} else if inaccessible_sugg.is_empty() {
350+
suggest_for_access(&mut err, help, accessible_sugg);
351+
} else {
352+
suggest_for_access(&mut err, help.clone(), accessible_sugg);
353+
suggest_for_privacy(&mut err, help, inaccessible_sugg);
354+
}
355+
},
356+
);
314357
}
315358
if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
316359
if needs_mut {
@@ -3089,49 +3132,69 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
30893132
}
30903133
}
30913134

3092-
fn suggest_use_candidates(&self, err: &mut Diag<'_>, msg: String, candidates: Vec<DefId>) {
3135+
fn suggest_use_candidates<F>(&self, candidates: Vec<DefId>, handle_candidates: F)
3136+
where
3137+
F: FnOnce(Vec<String>, Vec<String>, Span),
3138+
{
30933139
let parent_map = self.tcx.visible_parent_map(());
30943140

3095-
// Separate out candidates that must be imported with a glob, because they are named `_`
3096-
// and cannot be referred with their identifier.
3097-
let (candidates, globs): (Vec<_>, Vec<_>) = candidates.into_iter().partition(|trait_did| {
3098-
if let Some(parent_did) = parent_map.get(trait_did) {
3099-
// If the item is re-exported as `_`, we should suggest a glob-import instead.
3100-
if *parent_did != self.tcx.parent(*trait_did)
3101-
&& self
3102-
.tcx
3103-
.module_children(*parent_did)
3104-
.iter()
3105-
.filter(|child| child.res.opt_def_id() == Some(*trait_did))
3106-
.all(|child| child.ident.name == kw::Underscore)
3107-
{
3108-
return false;
3109-
}
3110-
}
3141+
let scope = self.tcx.parent_module_from_def_id(self.body_id);
3142+
let (accessible_candidates, inaccessible_candidates): (Vec<_>, Vec<_>) =
3143+
candidates.into_iter().partition(|id| {
3144+
let vis = self.tcx.visibility(*id);
3145+
vis.is_accessible_from(scope, self.tcx)
3146+
});
31113147

3112-
true
3113-
});
3148+
let sugg = |candidates: Vec<_>, visible| {
3149+
// Separate out candidates that must be imported with a glob, because they are named `_`
3150+
// and cannot be referred with their identifier.
3151+
let (candidates, globs): (Vec<_>, Vec<_>) =
3152+
candidates.into_iter().partition(|trait_did| {
3153+
if let Some(parent_did) = parent_map.get(trait_did) {
3154+
// If the item is re-exported as `_`, we should suggest a glob-import instead.
3155+
if *parent_did != self.tcx.parent(*trait_did)
3156+
&& self
3157+
.tcx
3158+
.module_children(*parent_did)
3159+
.iter()
3160+
.filter(|child| child.res.opt_def_id() == Some(*trait_did))
3161+
.all(|child| child.ident.name == kw::Underscore)
3162+
{
3163+
return false;
3164+
}
3165+
}
31143166

3115-
let module_did = self.tcx.parent_module_from_def_id(self.body_id);
3116-
let (module, _, _) = self.tcx.hir().get_module(module_did);
3117-
let span = module.spans.inject_use_span;
3167+
true
3168+
});
31183169

3119-
let path_strings = candidates.iter().map(|trait_did| {
3120-
format!("use {};\n", with_crate_prefix!(self.tcx.def_path_str(*trait_did)),)
3121-
});
3170+
let prefix = if visible { "use " } else { "" };
3171+
let postfix = if visible { ";" } else { "" };
3172+
let path_strings = candidates.iter().map(|trait_did| {
3173+
format!(
3174+
"{prefix}{}{postfix}\n",
3175+
with_crate_prefix!(self.tcx.def_path_str(*trait_did)),
3176+
)
3177+
});
31223178

3123-
let glob_path_strings = globs.iter().map(|trait_did| {
3124-
let parent_did = parent_map.get(trait_did).unwrap();
3125-
format!(
3126-
"use {}::*; // trait {}\n",
3127-
with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
3128-
self.tcx.item_name(*trait_did),
3129-
)
3130-
});
3131-
let mut sugg: Vec<_> = path_strings.chain(glob_path_strings).collect();
3132-
sugg.sort();
3179+
let glob_path_strings = globs.iter().map(|trait_did| {
3180+
let parent_did = parent_map.get(trait_did).unwrap();
3181+
format!(
3182+
"{prefix}{}::*{postfix} // trait {}\n",
3183+
with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
3184+
self.tcx.item_name(*trait_did),
3185+
)
3186+
});
3187+
let mut sugg: Vec<_> = path_strings.chain(glob_path_strings).collect();
3188+
sugg.sort();
3189+
sugg
3190+
};
31333191

3134-
err.span_suggestions(span, msg, sugg, Applicability::MaybeIncorrect);
3192+
let accessible_sugg = sugg(accessible_candidates, true);
3193+
let inaccessible_sugg = sugg(inaccessible_candidates, false);
3194+
3195+
let (module, _, _) = self.tcx.hir().get_module(scope);
3196+
let span = module.spans.inject_use_span;
3197+
handle_candidates(accessible_sugg, inaccessible_sugg, span);
31353198
}
31363199

31373200
fn suggest_valid_traits(
@@ -3155,21 +3218,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31553218
if explain {
31563219
err.help("items from traits can only be used if the trait is in scope");
31573220
}
3221+
31583222
let msg = format!(
3159-
"{this_trait_is} implemented but not in scope; perhaps you want to import \
3160-
{one_of_them}",
3223+
"{this_trait_is} implemented but not in scope",
31613224
this_trait_is = if candidates.len() == 1 {
31623225
format!(
31633226
"trait `{}` which provides `{item_name}` is",
31643227
self.tcx.item_name(candidates[0]),
31653228
)
31663229
} else {
31673230
format!("the following traits which provide `{item_name}` are")
3168-
},
3169-
one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
3231+
}
31703232
);
31713233

3172-
self.suggest_use_candidates(err, msg, candidates);
3234+
self.suggest_use_candidates(candidates, |accessible_sugg, inaccessible_sugg, span| {
3235+
let suggest_for_access = |err: &mut Diag<'_>, mut msg: String, sugg: Vec<_>| {
3236+
msg += &format!(
3237+
"; perhaps you want to import {one_of}",
3238+
one_of = if sugg.len() == 1 { "it" } else { "one of them" },
3239+
);
3240+
err.span_suggestions(span, msg, sugg, Applicability::MaybeIncorrect);
3241+
};
3242+
let suggest_for_privacy = |err: &mut Diag<'_>, sugg: Vec<String>| {
3243+
let msg = format!(
3244+
"{this_trait_is} implemented but not reachable",
3245+
this_trait_is = if sugg.len() == 1 {
3246+
format!("trait `{}` which provides `{item_name}` is", sugg[0].trim())
3247+
} else {
3248+
format!("the following traits which provide `{item_name}` are")
3249+
}
3250+
);
3251+
if sugg.len() == 1 {
3252+
err.help(msg);
3253+
} else {
3254+
err.span_suggestions(span, msg, sugg, Applicability::MaybeIncorrect);
3255+
}
3256+
};
3257+
if accessible_sugg.is_empty() {
3258+
// `inaccessible_sugg` must not be empty
3259+
suggest_for_privacy(err, inaccessible_sugg);
3260+
} else if inaccessible_sugg.is_empty() {
3261+
suggest_for_access(err, msg, accessible_sugg);
3262+
} else {
3263+
suggest_for_access(err, msg, accessible_sugg);
3264+
suggest_for_privacy(err, inaccessible_sugg);
3265+
}
3266+
});
3267+
31733268
if let Some(did) = edition_fix {
31743269
err.note(format!(
31753270
"'{}' is included in the prelude starting in Edition 2021",

compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use std::ops::Deref;
2222
/// e.g. closures defined within the function. For example:
2323
/// ```ignore (illustrative)
2424
/// fn foo() {
25-
/// bar(move|| { ... })
25+
/// bar(move || { ... })
2626
/// }
2727
/// ```
2828
/// Here, the function `foo()` and the closure passed to

compiler/rustc_lint/messages.ftl

+1
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,7 @@ lint_non_local_definitions_impl = non-local `impl` definition, `impl` blocks sho
549549
.without_trait = methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl`
550550
.with_trait = an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl`
551551
.bounds = `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type
552+
.doctest = make this doc-test a standalone test with its own `fn main() {"{"} ... {"}"}`
552553
.exception = items in an anonymous const item (`const _: () = {"{"} ... {"}"}`) are treated as in the same scope as the anonymous const's declaration
553554
.const_anon = use a const-anon item to suppress this lint
554555
.macro_to_change = the {$macro_kind} `{$macro_to_change}` defines the non-local `impl`, and may need to be changed

compiler/rustc_lint/src/lints.rs

+10-8
Original file line numberDiff line numberDiff line change
@@ -1358,6 +1358,7 @@ pub enum NonLocalDefinitionsDiag {
13581358
cargo_update: Option<NonLocalDefinitionsCargoUpdateNote>,
13591359
const_anon: Option<Option<Span>>,
13601360
move_to: Option<(Span, Vec<Span>)>,
1361+
doctest: bool,
13611362
may_remove: Option<(Span, String)>,
13621363
has_trait: bool,
13631364
self_ty_str: String,
@@ -1368,8 +1369,7 @@ pub enum NonLocalDefinitionsDiag {
13681369
depth: u32,
13691370
body_kind_descr: &'static str,
13701371
body_name: String,
1371-
help: Option<()>,
1372-
doctest_help: Option<()>,
1372+
doctest: bool,
13731373
cargo_update: Option<NonLocalDefinitionsCargoUpdateNote>,
13741374
},
13751375
}
@@ -1384,6 +1384,7 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag {
13841384
cargo_update,
13851385
const_anon,
13861386
move_to,
1387+
doctest,
13871388
may_remove,
13881389
has_trait,
13891390
self_ty_str,
@@ -1422,6 +1423,9 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag {
14221423
}
14231424
diag.span_help(ms, fluent::lint_non_local_definitions_impl_move_help);
14241425
}
1426+
if doctest {
1427+
diag.help(fluent::lint_doctest);
1428+
}
14251429

14261430
if let Some((span, part)) = may_remove {
14271431
diag.arg("may_remove_part", part);
@@ -1451,20 +1455,18 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag {
14511455
depth,
14521456
body_kind_descr,
14531457
body_name,
1454-
help,
1455-
doctest_help,
1458+
doctest,
14561459
cargo_update,
14571460
} => {
14581461
diag.primary_message(fluent::lint_non_local_definitions_macro_rules);
14591462
diag.arg("depth", depth);
14601463
diag.arg("body_kind_descr", body_kind_descr);
14611464
diag.arg("body_name", body_name);
14621465

1463-
if let Some(()) = help {
1464-
diag.help(fluent::lint_help);
1465-
}
1466-
if let Some(()) = doctest_help {
1466+
if doctest {
14671467
diag.help(fluent::lint_help_doctest);
1468+
} else {
1469+
diag.help(fluent::lint_help);
14681470
}
14691471

14701472
diag.note(fluent::lint_non_local);

0 commit comments

Comments
 (0)