Skip to content
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

Rollup of 9 pull requests #129933

Closed
wants to merge 26 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
102997a
Update Tests
veera-sivarajan Jul 13, 2024
764675e
Add Tests
veera-sivarajan Aug 6, 2024
f003e92
Don't Suggest Labeling `const` and `unsafe` Blocks
veera-sivarajan Aug 6, 2024
12de141
Suggest `impl Trait` for References to Bare Trait in Function Header
veera-sivarajan Jul 13, 2024
992b0b3
Document the broken C ABI of `wasm32-unknown-unknown`
alexcrichton Aug 26, 2024
28dc116
Don't ICE when dumping MIR of a synthetic coroutine body
compiler-errors Aug 28, 2024
8d3945d
Rename dump of coroutine by-move-body to be more consistent, adjust test
compiler-errors Aug 28, 2024
98106cf
Re-parent the by-move body
compiler-errors Aug 28, 2024
6f6a6bc
Non-exhaustive structs may be empty
Nadrieril Aug 10, 2024
5410900
Adjust `SanityCheck`.
nnethercote Sep 3, 2024
2aae619
Move `MirPass` to `rustc_mir_transform`.
nnethercote Sep 3, 2024
827fa43
Reduce visibility of `MirPass` and related things.
nnethercote Sep 3, 2024
0b2b03c
Clarify a comment.
nnethercote Sep 3, 2024
6188aae
do not attempt to prove unknowable goals
lcnr Sep 2, 2024
aa1f60e
rustc_driver_impl: remove some old dead logic
RalfJung Sep 3, 2024
17f3f92
include 1.80.1 release notes on master
pietroalbini Sep 3, 2024
2d6d6a8
Updates/clarifications
alexcrichton Aug 27, 2024
4b38ef6
Rollup merge of #127692 - veera-sivarajan:bugfix-125139, r=estebank
matthiaskrgr Sep 3, 2024
e3155ab
Rollup merge of #128701 - veera-sivarajan:fix-128604, r=estebank
matthiaskrgr Sep 3, 2024
4e6fa3c
Rollup merge of #128934 - Nadrieril:fix-empty-non-exhaustive, r=compi…
matthiaskrgr Sep 3, 2024
b9c99b6
Rollup merge of #129630 - alexcrichton:document-broken-c-abi-on-wasm3…
matthiaskrgr Sep 3, 2024
aa669ef
Rollup merge of #129706 - compiler-errors:scratch, r=estebank
matthiaskrgr Sep 3, 2024
b777ba9
Rollup merge of #129896 - lcnr:bail-on-unknowable, r=jackh726
matthiaskrgr Sep 3, 2024
7a8ffbc
Rollup merge of #129926 - nnethercote:mv-SanityCheck-and-MirPass, r=c…
matthiaskrgr Sep 3, 2024
b447cd5
Rollup merge of #129928 - RalfJung:rustc_driver_impl-crt-static, r=co…
matthiaskrgr Sep 3, 2024
67c3113
Rollup merge of #129930 - ferrocene:pa-relnotes-1801, r=pietroalbini
matthiaskrgr Sep 3, 2024
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
Prev Previous commit
Next Next commit
Suggest impl Trait for References to Bare Trait in Function Header
  • Loading branch information
veera-sivarajan committed Aug 19, 2024
commit 12de141df2d247177e9ca0498ba99bd433cfa500
78 changes: 55 additions & 23 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
return;
};
let sugg = self.add_generic_param_suggestion(generics, self_ty.span, &impl_trait_name);
if sugg.is_empty() {
return;
};
diag.multipart_suggestion(
format!(
"alternatively use a blanket implementation to implement `{of_trait_name}` for \
Expand Down Expand Up @@ -157,6 +154,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id;
// FIXME: If `type_alias_impl_trait` is enabled, also look for `Trait0<Ty = Trait1>`
// and suggest `Trait0<Ty = impl Trait1>`.
// Functions are found in three different contexts.
// 1. Independent functions
// 2. Functions inside trait blocks
// 3. Functions inside impl blocks
let (sig, generics, owner) = match tcx.hir_node_by_def_id(parent_id) {
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, generics, _), .. }) => {
(sig, generics, None)
Expand All @@ -167,13 +168,21 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
owner_id,
..
}) => (sig, generics, Some(tcx.parent(owner_id.to_def_id()))),
hir::Node::ImplItem(hir::ImplItem {
kind: hir::ImplItemKind::Fn(sig, _),
generics,
owner_id,
..
}) => (sig, generics, Some(tcx.parent(owner_id.to_def_id()))),
_ => return false,
};
let Ok(trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else {
return false;
};
let impl_sugg = vec![(self_ty.span.shrink_to_lo(), "impl ".to_string())];
let mut is_downgradable = true;

// Check if trait object is safe for suggesting dynamic dispatch.
let is_object_safe = match self_ty.kind {
hir::TyKind::TraitObject(objects, ..) => {
objects.iter().all(|o| match o.trait_ref.path.res {
Expand All @@ -189,8 +198,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}
_ => false,
};

let borrowed = matches!(
tcx.parent_hir_node(self_ty.hir_id),
hir::Node::Ty(hir::Ty { kind: hir::TyKind::Ref(..), .. })
);

// Suggestions for function return type.
if let hir::FnRetTy::Return(ty) = sig.decl.output
&& ty.hir_id == self_ty.hir_id
&& ty.peel_refs().hir_id == self_ty.hir_id
{
let pre = if !is_object_safe {
format!("`{trait_name}` is not object safe, ")
Expand All @@ -201,14 +217,26 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
"{pre}use `impl {trait_name}` to return an opaque type, as long as you return a \
single underlying type",
);

diag.multipart_suggestion_verbose(msg, impl_sugg, Applicability::MachineApplicable);

// Suggest `Box<dyn Trait>` for return type
if is_object_safe {
diag.multipart_suggestion_verbose(
"alternatively, you can return an owned trait object",
// If the return type is `&Trait`, we don't want
// the ampersand to be displayed in the `Box<dyn Trait>`
// suggestion.
let suggestion = if borrowed {
vec![(ty.span, format!("Box<dyn {trait_name}>"))]
} else {
vec![
(ty.span.shrink_to_lo(), "Box<dyn ".to_string()),
(ty.span.shrink_to_hi(), ">".to_string()),
],
]
};

diag.multipart_suggestion_verbose(
"alternatively, you can return an owned trait object",
suggestion,
Applicability::MachineApplicable,
);
} else if is_downgradable {
Expand All @@ -217,39 +245,43 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}
return true;
}

// Suggestions for function parameters.
for ty in sig.decl.inputs {
if ty.hir_id != self_ty.hir_id {
if ty.peel_refs().hir_id != self_ty.hir_id {
continue;
}
let sugg = self.add_generic_param_suggestion(generics, self_ty.span, &trait_name);
if !sugg.is_empty() {
diag.multipart_suggestion_verbose(
format!("use a new generic type parameter, constrained by `{trait_name}`"),
sugg,
Applicability::MachineApplicable,
);
diag.multipart_suggestion_verbose(
"you can also use an opaque type, but users won't be able to specify the type \
parameter when calling the `fn`, having to rely exclusively on type inference",
impl_sugg,
Applicability::MachineApplicable,
);
}
diag.multipart_suggestion_verbose(
format!("use a new generic type parameter, constrained by `{trait_name}`"),
sugg,
Applicability::MachineApplicable,
);
diag.multipart_suggestion_verbose(
"you can also use an opaque type, but users won't be able to specify the type \
parameter when calling the `fn`, having to rely exclusively on type inference",
impl_sugg,
Applicability::MachineApplicable,
);
if !is_object_safe {
diag.note(format!("`{trait_name}` it is not object safe, so it can't be `dyn`"));
if is_downgradable {
// We'll emit the object safety error already, with a structured suggestion.
diag.downgrade_to_delayed_bug();
}
} else {
// No ampersand in suggestion if it's borrowed already
let (dyn_str, paren_dyn_str) =
if borrowed { ("dyn ", "(dyn ") } else { ("&dyn ", "&(dyn ") };

let sugg = if let hir::TyKind::TraitObject([_, _, ..], _, _) = self_ty.kind {
// There are more than one trait bound, we need surrounding parentheses.
vec![
(self_ty.span.shrink_to_lo(), "&(dyn ".to_string()),
(self_ty.span.shrink_to_lo(), paren_dyn_str.to_string()),
(self_ty.span.shrink_to_hi(), ")".to_string()),
]
} else {
vec![(self_ty.span.shrink_to_lo(), "&dyn ".to_string())]
vec![(self_ty.span.shrink_to_lo(), dyn_str.to_string())]
};
diag.multipart_suggestion_verbose(
format!(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4925,24 +4925,32 @@ impl<'v> Visitor<'v> for AwaitsVisitor {
}
}

/// Suggest a new type parameter name for diagnostic purposes.
///
/// `name` is the preferred name you'd like to suggest if it's not in use already.
pub trait NextTypeParamName {
fn next_type_param_name(&self, name: Option<&str>) -> String;
}

impl NextTypeParamName for &[hir::GenericParam<'_>] {
fn next_type_param_name(&self, name: Option<&str>) -> String {
// This is the list of possible parameter names that we might suggest.
// Type names are usually single letters in uppercase. So convert the first letter of input string to uppercase.
let name = name.and_then(|n| n.chars().next()).map(|c| c.to_uppercase().to_string());
let name = name.as_deref();

// This is the list of possible parameter names that we might suggest.
let possible_names = [name.unwrap_or("T"), "T", "U", "V", "X", "Y", "Z", "A", "B", "C"];
let used_names = self

// Filter out used names based on `filter_fn`.
let used_names: Vec<Symbol> = self
.iter()
.filter_map(|p| match p.name {
.filter_map(|param| match param.name {
hir::ParamName::Plain(ident) => Some(ident.name),
_ => None,
})
.collect::<Vec<_>>();
.collect();

// Find a name from `possible_names` that is not in `used_names`.
possible_names
.iter()
.find(|n| !used_names.contains(&Symbol::intern(n)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ impl IceCream {

fn parrot() -> &mut Trait {
//~^ ERROR: missing lifetime specifier
//~| ERROR: cannot return a mutable reference to a bare trait
//~| ERROR: trait objects must include the `dyn` keyword
&mut Type
//~^ ERROR: cannot return reference to temporary value
}
Expand Down Expand Up @@ -86,12 +86,12 @@ trait Sing {

fn parrot() -> &mut Trait {
//~^ ERROR: missing lifetime specifier
//~| ERROR: cannot return a mutable reference to a bare trait
//~| ERROR: trait objects must include the `dyn` keyword
&mut Type
//~^ ERROR: cannot return reference to temporary value
}
}

fn foo(_: &Trait) {}
//~^ ERROR: trait objects must include the `dyn` keyword

Expand Down Expand Up @@ -134,7 +134,7 @@ fn puppy<'a>() -> &'a Trait {

fn parrot() -> &mut Trait {
//~^ ERROR: missing lifetime specifier
//~| ERROR: cannot return a mutable reference to a bare trait
//~| ERROR: trait objects must include the `dyn` keyword
&mut Type
//~^ ERROR: cannot return reference to temporary value
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,8 +298,8 @@ LL | fn cat() -> &Trait;
|
help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
|
LL | fn cat<'a>() -> &'a impl Trait;
| ++++ +++++++
LL | fn cat() -> &impl Trait;
| ++++
help: alternatively, you can return an owned trait object
|
LL | fn cat() -> Box<dyn Trait>;
Expand All @@ -313,8 +313,8 @@ LL | fn dog<'a>() -> &Trait {
|
help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
|
LL | fn dog<'b, 'a>() -> &'b impl Trait {
| +++ +++++++
LL | fn dog<'a>() -> &impl Trait {
| ++++
help: alternatively, you can return an owned trait object
|
LL | fn dog<'a>() -> Box<dyn Trait> {
Expand Down Expand Up @@ -350,16 +350,16 @@ help: alternatively, you can return an owned trait object
LL | fn puppy<'a>() -> Box<dyn Trait> {
| ~~~~~~~~~~~~~~

error[E0782]: cannot return a mutable reference to a bare trait
error[E0782]: trait objects must include the `dyn` keyword
--> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:87:25
|
LL | fn parrot() -> &mut Trait {
| ^^^^^
|
help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
|
LL | fn parrot() -> impl Trait {
| ~~~~~~~~~~
LL | fn parrot() -> &mut impl Trait {
| ++++
help: alternatively, you can return an owned trait object
|
LL | fn parrot() -> Box<dyn Trait> {
Expand Down Expand Up @@ -449,8 +449,8 @@ LL | fn cat() -> &Trait {
|
help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
|
LL | fn cat<'a>() -> &'a impl Trait {
| ++++ +++++++
LL | fn cat() -> &impl Trait {
| ++++
help: alternatively, you can return an owned trait object
|
LL | fn cat() -> Box<dyn Trait> {
Expand All @@ -464,8 +464,8 @@ LL | fn dog<'a>() -> &Trait {
|
help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
|
LL | fn dog<'b, 'a>() -> &'b impl Trait {
| +++ +++++++
LL | fn dog<'a>() -> &impl Trait {
| ++++
help: alternatively, you can return an owned trait object
|
LL | fn dog<'a>() -> Box<dyn Trait> {
Expand Down Expand Up @@ -501,16 +501,16 @@ help: alternatively, you can return an owned trait object
LL | fn puppy<'a>() -> Box<dyn Trait> {
| ~~~~~~~~~~~~~~

error[E0782]: cannot return a mutable reference to a bare trait
error[E0782]: trait objects must include the `dyn` keyword
--> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:135:21
|
LL | fn parrot() -> &mut Trait {
| ^^^^^
|
help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
|
LL | fn parrot() -> impl Trait {
| ~~~~~~~~~~
LL | fn parrot() -> &mut impl Trait {
| ++++
help: alternatively, you can return an owned trait object
|
LL | fn parrot() -> Box<dyn Trait> {
Expand Down Expand Up @@ -600,8 +600,8 @@ LL | fn cat() -> &Trait {
|
help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
|
LL | fn cat<'a>() -> &'a impl Trait {
| ++++ +++++++
LL | fn cat() -> &impl Trait {
| ++++
help: alternatively, you can return an owned trait object
|
LL | fn cat() -> Box<dyn Trait> {
Expand All @@ -615,8 +615,8 @@ LL | fn dog<'a>() -> &Trait {
|
help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
|
LL | fn dog<'b, 'a>() -> &'b impl Trait {
| +++ +++++++
LL | fn dog<'a>() -> &impl Trait {
| ++++
help: alternatively, you can return an owned trait object
|
LL | fn dog<'a>() -> Box<dyn Trait> {
Expand Down Expand Up @@ -652,16 +652,16 @@ help: alternatively, you can return an owned trait object
LL | fn puppy<'a>() -> Box<dyn Trait> {
| ~~~~~~~~~~~~~~

error[E0782]: cannot return a mutable reference to a bare trait
error[E0782]: trait objects must include the `dyn` keyword
--> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:44:25
|
LL | fn parrot() -> &mut Trait {
| ^^^^^
|
help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
|
LL | fn parrot() -> impl Trait {
| ~~~~~~~~~~
LL | fn parrot() -> &mut impl Trait {
| ++++
help: alternatively, you can return an owned trait object
|
LL | fn parrot() -> Box<dyn Trait> {
Expand Down
Loading