Skip to content

Commit d333744

Browse files
committed
Account for type Alias = dyn Trait; in unsized return suggestion
``` error[E0746]: return type cannot have an unboxed trait object --> tests/ui/unsized/issue-91801.rs:8:77 | 8 | fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> Validator<'a> { | ^^^^^^^^^^^^^ doesn't have a size known at compile-time -Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs:566:39 | help: box the return type to make a boxed trait object, and wrap all of the returned values in `Box::new` | 8 | fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> Box<Validator<'a>> { | ++++ + help: alternatively, you might be able to borrow from one of the function's arguments | 8 | fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> &Validator<'a> { | + ```
1 parent 414b083 commit d333744

File tree

2 files changed

+56
-16
lines changed

2 files changed

+56
-16
lines changed

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1801,13 +1801,43 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
18011801
let Some(fn_decl) = self.tcx.hir_node(fn_id).fn_decl() else {
18021802
return false;
18031803
};
1804-
let hir::FnRetTy::Return(hir::Ty {
1805-
kind: hir::TyKind::TraitObject(traits @ [tr, ..], _lt, syn),
1806-
span,
1807-
..
1808-
}) = fn_decl.output
1809-
else {
1810-
return false;
1804+
let (traits, tr, syn, span, can_be_impl) = match fn_decl.output {
1805+
hir::FnRetTy::Return(hir::Ty {
1806+
kind: hir::TyKind::TraitObject(traits @ [tr, ..], _lt, syn),
1807+
span,
1808+
..
1809+
}) => (traits, tr, syn, span, true),
1810+
hir::FnRetTy::Return(hir::Ty {
1811+
kind:
1812+
hir::TyKind::Path(hir::QPath::Resolved(
1813+
None,
1814+
hir::Path { res: hir::def::Res::Def(DefKind::TyAlias, def_id), .. },
1815+
)),
1816+
span,
1817+
..
1818+
}) => {
1819+
if let ty::Dynamic(..) = self.tcx.type_of(def_id).instantiate_identity().kind() {
1820+
// We have a `type Alias = dyn Trait;` and a return type `-> Alias`.
1821+
if let Some(def_id) = def_id.as_local()
1822+
&& let node = self.tcx.hir_node_by_def_id(def_id)
1823+
&& let Some(hir::Ty {
1824+
kind: hir::TyKind::TraitObject(traits @ [tr, ..], _lt, syn),
1825+
..
1826+
}) = node.ty()
1827+
{
1828+
(traits, tr, syn, span, false)
1829+
} else {
1830+
let mut span: MultiSpan = (*span).into();
1831+
span.push_span_label(self.tcx.def_span(def_id), "defined here");
1832+
err.span_note(span, "the return type is a type alias to a trait object");
1833+
err.help("consider boxing or borrowing it");
1834+
return false;
1835+
}
1836+
} else {
1837+
return false;
1838+
}
1839+
}
1840+
_ => return false,
18111841
};
18121842

18131843
// Suggest `-> impl Trait`
@@ -1841,14 +1871,17 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
18411871
let mut alternatively = "";
18421872
if all_same_ty || visitor.returns.len() == 1 {
18431873
// We're certain that `impl Trait` will work.
1844-
err.span_suggestion_verbose(
1845-
// This will work for both `Dyn` and `None` object syntax.
1846-
span.until(tr.span),
1847-
"return an `impl Trait` instead of a `dyn Trait`",
1848-
"impl ",
1849-
Applicability::MachineApplicable,
1850-
);
1851-
alternatively = "alternatively, ";
1874+
if can_be_impl {
1875+
// We know it's not a `type Alias = dyn Trait;`.
1876+
err.span_suggestion_verbose(
1877+
// This will work for both `Dyn` and `None` object syntax.
1878+
span.until(tr.span),
1879+
"return an `impl Trait` instead of a `dyn Trait`",
1880+
"impl ",
1881+
Applicability::MachineApplicable,
1882+
);
1883+
alternatively = "alternatively, ";
1884+
}
18521885
} else {
18531886
let mut span: MultiSpan =
18541887
ret_tys.iter().map(|(expr, _)| expr.span).collect::<Vec<Span>>().into();

tests/ui/unsized/issue-91801.stderr

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,14 @@ error[E0746]: return type cannot have an unboxed trait object
44
LL | fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> Validator<'a> {
55
| ^^^^^^^^^^^^^ doesn't have a size known at compile-time
66
|
7-
= note: the return type of a function must have a statically known size
7+
help: box the return type to make a boxed trait object, and wrap all of the returned values in `Box::new`
8+
|
9+
LL | fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> Box<Validator<'a>> {
10+
| ++++ +
11+
help: alternatively, you might be able to borrow from one of the function's arguments
12+
|
13+
LL | fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> &Validator<'a> {
14+
| +
815

916
error: aborting due to 1 previous error
1017

0 commit comments

Comments
 (0)