Skip to content

Commit

Permalink
Auto merge of rust-lang#126642 - GuillaumeGomez:rollup-ofclymo, r=Gui…
Browse files Browse the repository at this point in the history
…llaumeGomez

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
  • Loading branch information
bors committed Jun 18, 2024
2 parents 8fcd4dd + ef8c24a commit f11ef80
Show file tree
Hide file tree
Showing 46 changed files with 724 additions and 276 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ build/
/src/tools/x/target
# Created by default with `src/ci/docker/run.sh`
/obj/
/rustc-ice*

## Temporary files
*~
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3476,6 +3476,7 @@ dependencies = [
"object 0.34.0",
"regex",
"similar",
"walkdir",
"wasmparser",
]

Expand Down
11 changes: 10 additions & 1 deletion compiler/rustc_const_eval/src/interpret/discriminant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,16 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
variant_index: VariantIdx,
) -> InterpResult<'tcx, Option<(ScalarInt, usize)>> {
match self.layout_of(ty)?.variants {
abi::Variants::Single { .. } => Ok(None),
abi::Variants::Single { .. } => {
// The tag of a `Single` enum is like the tag of the niched
// variant: there's no tag as the discriminant is encoded
// entirely implicitly. If `write_discriminant` ever hits this
// case, we do a "validation read" to ensure the the right
// discriminant is encoded implicitly, so any attempt to write
// the wrong discriminant for a `Single` enum will reliably
// result in UB.
Ok(None)
}

abi::Variants::Multiple {
tag_encoding: TagEncoding::Direct,
Expand Down
185 changes: 140 additions & 45 deletions compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,14 +303,57 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
if !candidates.is_empty() {
let help = format!(
"{an}other candidate{s} {were} found in the following trait{s}, perhaps \
add a `use` for {one_of_them}:",
"{an}other candidate{s} {were} found in the following trait{s}",
an = if candidates.len() == 1 { "an" } else { "" },
s = pluralize!(candidates.len()),
were = pluralize!("was", candidates.len()),
one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
);
self.suggest_use_candidates(&mut err, help, candidates);
self.suggest_use_candidates(
candidates,
|accessible_sugg, inaccessible_sugg, span| {
let suggest_for_access =
|err: &mut Diag<'_>, mut msg: String, sugg: Vec<_>| {
msg += &format!(
", perhaps add a `use` for {one_of_them}:",
one_of_them =
if sugg.len() == 1 { "it" } else { "one_of_them" },
);
err.span_suggestions(
span,
msg,
sugg,
Applicability::MaybeIncorrect,
);
};
let suggest_for_privacy =
|err: &mut Diag<'_>, mut msg: String, sugg: Vec<String>| {
if sugg.len() == 1 {
let msg = format!("\
trait `{}` provides `{item_name}` is implemented but not reachable",
sugg[0].trim()
);
err.help(msg);
} else {
msg += &format!(" but {} not reachable", pluralize!("is", sugg.len()));
err.span_suggestions(
span,
msg,
sugg,
Applicability::MaybeIncorrect,
);
}
};
if accessible_sugg.is_empty() {
// `inaccessible_sugg` must not be empty
suggest_for_privacy(&mut err, help, inaccessible_sugg);
} else if inaccessible_sugg.is_empty() {
suggest_for_access(&mut err, help, accessible_sugg);
} else {
suggest_for_access(&mut err, help.clone(), accessible_sugg);
suggest_for_privacy(&mut err, help, inaccessible_sugg);
}
},
);
}
if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
if needs_mut {
Expand Down Expand Up @@ -3089,49 +3132,69 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}

fn suggest_use_candidates(&self, err: &mut Diag<'_>, msg: String, candidates: Vec<DefId>) {
fn suggest_use_candidates<F>(&self, candidates: Vec<DefId>, handle_candidates: F)
where
F: FnOnce(Vec<String>, Vec<String>, Span),
{
let parent_map = self.tcx.visible_parent_map(());

// Separate out candidates that must be imported with a glob, because they are named `_`
// and cannot be referred with their identifier.
let (candidates, globs): (Vec<_>, Vec<_>) = candidates.into_iter().partition(|trait_did| {
if let Some(parent_did) = parent_map.get(trait_did) {
// If the item is re-exported as `_`, we should suggest a glob-import instead.
if *parent_did != self.tcx.parent(*trait_did)
&& self
.tcx
.module_children(*parent_did)
.iter()
.filter(|child| child.res.opt_def_id() == Some(*trait_did))
.all(|child| child.ident.name == kw::Underscore)
{
return false;
}
}
let scope = self.tcx.parent_module_from_def_id(self.body_id);
let (accessible_candidates, inaccessible_candidates): (Vec<_>, Vec<_>) =
candidates.into_iter().partition(|id| {
let vis = self.tcx.visibility(*id);
vis.is_accessible_from(scope, self.tcx)
});

true
});
let sugg = |candidates: Vec<_>, visible| {
// Separate out candidates that must be imported with a glob, because they are named `_`
// and cannot be referred with their identifier.
let (candidates, globs): (Vec<_>, Vec<_>) =
candidates.into_iter().partition(|trait_did| {
if let Some(parent_did) = parent_map.get(trait_did) {
// If the item is re-exported as `_`, we should suggest a glob-import instead.
if *parent_did != self.tcx.parent(*trait_did)
&& self
.tcx
.module_children(*parent_did)
.iter()
.filter(|child| child.res.opt_def_id() == Some(*trait_did))
.all(|child| child.ident.name == kw::Underscore)
{
return false;
}
}

let module_did = self.tcx.parent_module_from_def_id(self.body_id);
let (module, _, _) = self.tcx.hir().get_module(module_did);
let span = module.spans.inject_use_span;
true
});

let path_strings = candidates.iter().map(|trait_did| {
format!("use {};\n", with_crate_prefix!(self.tcx.def_path_str(*trait_did)),)
});
let prefix = if visible { "use " } else { "" };
let postfix = if visible { ";" } else { "" };
let path_strings = candidates.iter().map(|trait_did| {
format!(
"{prefix}{}{postfix}\n",
with_crate_prefix!(self.tcx.def_path_str(*trait_did)),
)
});

let glob_path_strings = globs.iter().map(|trait_did| {
let parent_did = parent_map.get(trait_did).unwrap();
format!(
"use {}::*; // trait {}\n",
with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
self.tcx.item_name(*trait_did),
)
});
let mut sugg: Vec<_> = path_strings.chain(glob_path_strings).collect();
sugg.sort();
let glob_path_strings = globs.iter().map(|trait_did| {
let parent_did = parent_map.get(trait_did).unwrap();
format!(
"{prefix}{}::*{postfix} // trait {}\n",
with_crate_prefix!(self.tcx.def_path_str(*parent_did)),
self.tcx.item_name(*trait_did),
)
});
let mut sugg: Vec<_> = path_strings.chain(glob_path_strings).collect();
sugg.sort();
sugg
};

err.span_suggestions(span, msg, sugg, Applicability::MaybeIncorrect);
let accessible_sugg = sugg(accessible_candidates, true);
let inaccessible_sugg = sugg(inaccessible_candidates, false);

let (module, _, _) = self.tcx.hir().get_module(scope);
let span = module.spans.inject_use_span;
handle_candidates(accessible_sugg, inaccessible_sugg, span);
}

fn suggest_valid_traits(
Expand All @@ -3155,21 +3218,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if explain {
err.help("items from traits can only be used if the trait is in scope");
}

let msg = format!(
"{this_trait_is} implemented but not in scope; perhaps you want to import \
{one_of_them}",
"{this_trait_is} implemented but not in scope",
this_trait_is = if candidates.len() == 1 {
format!(
"trait `{}` which provides `{item_name}` is",
self.tcx.item_name(candidates[0]),
)
} else {
format!("the following traits which provide `{item_name}` are")
},
one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
}
);

self.suggest_use_candidates(err, msg, candidates);
self.suggest_use_candidates(candidates, |accessible_sugg, inaccessible_sugg, span| {
let suggest_for_access = |err: &mut Diag<'_>, mut msg: String, sugg: Vec<_>| {
msg += &format!(
"; perhaps you want to import {one_of}",
one_of = if sugg.len() == 1 { "it" } else { "one of them" },
);
err.span_suggestions(span, msg, sugg, Applicability::MaybeIncorrect);
};
let suggest_for_privacy = |err: &mut Diag<'_>, sugg: Vec<String>| {
let msg = format!(
"{this_trait_is} implemented but not reachable",
this_trait_is = if sugg.len() == 1 {
format!("trait `{}` which provides `{item_name}` is", sugg[0].trim())
} else {
format!("the following traits which provide `{item_name}` are")
}
);
if sugg.len() == 1 {
err.help(msg);
} else {
err.span_suggestions(span, msg, sugg, Applicability::MaybeIncorrect);
}
};
if accessible_sugg.is_empty() {
// `inaccessible_sugg` must not be empty
suggest_for_privacy(err, inaccessible_sugg);
} else if inaccessible_sugg.is_empty() {
suggest_for_access(err, msg, accessible_sugg);
} else {
suggest_for_access(err, msg, accessible_sugg);
suggest_for_privacy(err, inaccessible_sugg);
}
});

if let Some(did) = edition_fix {
err.note(format!(
"'{}' is included in the prelude starting in Edition 2021",
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use std::ops::Deref;
/// e.g. closures defined within the function. For example:
/// ```ignore (illustrative)
/// fn foo() {
/// bar(move|| { ... })
/// bar(move || { ... })
/// }
/// ```
/// Here, the function `foo()` and the closure passed to
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_lint/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,7 @@ lint_non_local_definitions_impl = non-local `impl` definition, `impl` blocks sho
.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`
.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`
.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
.doctest = make this doc-test a standalone test with its own `fn main() {"{"} ... {"}"}`
.exception = items in an anonymous const item (`const _: () = {"{"} ... {"}"}`) are treated as in the same scope as the anonymous const's declaration
.const_anon = use a const-anon item to suppress this lint
.macro_to_change = the {$macro_kind} `{$macro_to_change}` defines the non-local `impl`, and may need to be changed
Expand Down
18 changes: 10 additions & 8 deletions compiler/rustc_lint/src/lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1358,6 +1358,7 @@ pub enum NonLocalDefinitionsDiag {
cargo_update: Option<NonLocalDefinitionsCargoUpdateNote>,
const_anon: Option<Option<Span>>,
move_to: Option<(Span, Vec<Span>)>,
doctest: bool,
may_remove: Option<(Span, String)>,
has_trait: bool,
self_ty_str: String,
Expand All @@ -1368,8 +1369,7 @@ pub enum NonLocalDefinitionsDiag {
depth: u32,
body_kind_descr: &'static str,
body_name: String,
help: Option<()>,
doctest_help: Option<()>,
doctest: bool,
cargo_update: Option<NonLocalDefinitionsCargoUpdateNote>,
},
}
Expand All @@ -1384,6 +1384,7 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag {
cargo_update,
const_anon,
move_to,
doctest,
may_remove,
has_trait,
self_ty_str,
Expand Down Expand Up @@ -1422,6 +1423,9 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag {
}
diag.span_help(ms, fluent::lint_non_local_definitions_impl_move_help);
}
if doctest {
diag.help(fluent::lint_doctest);
}

if let Some((span, part)) = may_remove {
diag.arg("may_remove_part", part);
Expand Down Expand Up @@ -1451,20 +1455,18 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag {
depth,
body_kind_descr,
body_name,
help,
doctest_help,
doctest,
cargo_update,
} => {
diag.primary_message(fluent::lint_non_local_definitions_macro_rules);
diag.arg("depth", depth);
diag.arg("body_kind_descr", body_kind_descr);
diag.arg("body_name", body_name);

if let Some(()) = help {
diag.help(fluent::lint_help);
}
if let Some(()) = doctest_help {
if doctest {
diag.help(fluent::lint_help_doctest);
} else {
diag.help(fluent::lint_help);
}

diag.note(fluent::lint_non_local);
Expand Down
Loading

0 comments on commit f11ef80

Please sign in to comment.