review comments

This commit is contained in:
Esteban Küber 2020-01-15 11:14:05 -08:00
parent c305ac31c0
commit d7a6212401
8 changed files with 205 additions and 217 deletions

View File

@ -25,7 +25,6 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_hir::intravisit::Visitor;
use rustc_span::source_map::SourceMap; use rustc_span::source_map::SourceMap;
use rustc_span::{ExpnKind, Span, DUMMY_SP}; use rustc_span::{ExpnKind, Span, DUMMY_SP};
use std::fmt; use std::fmt;
@ -1411,34 +1410,3 @@ pub fn suggest_constraining_type_param(
} }
false false
} }
/// Collect all the returned expressions within the input expression.
/// Used to point at the return spans when we want to suggest some change to them.
struct ReturnsVisitor<'v>(Vec<&'v hir::Expr<'v>>);
impl<'v> Visitor<'v> for ReturnsVisitor<'v> {
type Map = rustc::hir::map::Map<'v>;
fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<'_, Self::Map> {
hir::intravisit::NestedVisitorMap::None
}
fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
match ex.kind {
hir::ExprKind::Ret(Some(ex)) => self.0.push(ex),
_ => {}
}
hir::intravisit::walk_expr(self, ex);
}
fn visit_body(&mut self, body: &'v hir::Body<'v>) {
if body.generator_kind().is_none() {
if let hir::ExprKind::Block(block, None) = body.value.kind {
if let Some(expr) = block.expr {
self.0.push(expr);
}
}
}
hir::intravisit::walk_body(self, body);
}
}

View File

@ -563,157 +563,159 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
let hir = self.tcx.hir(); let hir = self.tcx.hir();
let parent_node = hir.get_parent_node(obligation.cause.body_id); let parent_node = hir.get_parent_node(obligation.cause.body_id);
let node = hir.find(parent_node); let node = hir.find(parent_node);
if let Some(hir::Node::Item(hir::Item { let (sig, body_id) = if let Some(hir::Node::Item(hir::Item {
kind: hir::ItemKind::Fn(sig, _, body_id), .. kind: hir::ItemKind::Fn(sig, _, body_id),
..
})) = node })) = node
{ {
let body = hir.body(*body_id); (sig, body_id)
let trait_ref = self.resolve_vars_if_possible(trait_ref); } else {
let ty = trait_ref.skip_binder().self_ty(); return false;
let is_object_safe; };
match ty.kind { let body = hir.body(*body_id);
ty::Dynamic(predicates, _) => { let trait_ref = self.resolve_vars_if_possible(trait_ref);
// The `dyn Trait` is not object safe, do not suggest `Box<dyn Trait>`. let ty = trait_ref.skip_binder().self_ty();
is_object_safe = predicates.principal_def_id().map_or(true, |def_id| { let is_object_safe = match ty.kind {
!object_safety_violations(self.tcx, def_id).is_empty() ty::Dynamic(predicates, _) => {
}) // If the `dyn Trait` is not object safe, do not suggest `Box<dyn Trait>`.
} predicates
// We only want to suggest `impl Trait` to `dyn Trait`s. .principal_def_id()
// For example, `fn foo() -> str` needs to be filtered out. .map_or(true, |def_id| object_safety_violations(self.tcx, def_id).is_empty())
_ => return false,
} }
// We only want to suggest `impl Trait` to `dyn Trait`s.
// For example, `fn foo() -> str` needs to be filtered out.
_ => return false,
};
let ret_ty = if let hir::FunctionRetTy::Return(ret_ty) = sig.decl.output { let ret_ty = if let hir::FunctionRetTy::Return(ret_ty) = sig.decl.output {
ret_ty ret_ty
} else { } else {
return false; return false;
}; };
// Use `TypeVisitor` instead of the output type directly to find the span of `ty` for // Use `TypeVisitor` instead of the output type directly to find the span of `ty` for
// cases like `fn foo() -> (dyn Trait, i32) {}`. // cases like `fn foo() -> (dyn Trait, i32) {}`.
// Recursively look for `TraitObject` types and if there's only one, use that span to // Recursively look for `TraitObject` types and if there's only one, use that span to
// suggest `impl Trait`. // suggest `impl Trait`.
// Visit to make sure there's a single `return` type to suggest `impl Trait`, // Visit to make sure there's a single `return` type to suggest `impl Trait`,
// otherwise suggest using `Box<dyn Trait>` or an enum. // otherwise suggest using `Box<dyn Trait>` or an enum.
let mut visitor = ReturnsVisitor(vec![]); let mut visitor = ReturnsVisitor(vec![]);
visitor.visit_body(&body); visitor.visit_body(&body);
let tables = self.in_progress_tables.map(|t| t.borrow()).unwrap(); let tables = self.in_progress_tables.map(|t| t.borrow()).unwrap();
let mut all_returns_conform_to_trait = true; let mut all_returns_conform_to_trait = true;
let mut all_returns_have_same_type = true; let mut all_returns_have_same_type = true;
let mut last_ty = None; let mut last_ty = None;
if let Some(ty_ret_ty) = tables.node_type_opt(ret_ty.hir_id) { if let Some(ty_ret_ty) = tables.node_type_opt(ret_ty.hir_id) {
let cause = ObligationCause::misc(ret_ty.span, ret_ty.hir_id); let cause = ObligationCause::misc(ret_ty.span, ret_ty.hir_id);
let param_env = ty::ParamEnv::empty(); let param_env = ty::ParamEnv::empty();
if let ty::Dynamic(predicates, _) = &ty_ret_ty.kind { if let ty::Dynamic(predicates, _) = &ty_ret_ty.kind {
for expr in &visitor.0 { for expr in &visitor.0 {
if let Some(returned_ty) = tables.node_type_opt(expr.hir_id) { if let Some(returned_ty) = tables.node_type_opt(expr.hir_id) {
all_returns_have_same_type &= all_returns_have_same_type &=
Some(returned_ty) == last_ty || last_ty.is_none(); Some(returned_ty) == last_ty || last_ty.is_none();
last_ty = Some(returned_ty); last_ty = Some(returned_ty);
for predicate in predicates.iter() { for predicate in predicates.iter() {
let pred = predicate.with_self_ty(self.tcx, returned_ty); let pred = predicate.with_self_ty(self.tcx, returned_ty);
let obl = Obligation::new(cause.clone(), param_env, pred); let obl = Obligation::new(cause.clone(), param_env, pred);
all_returns_conform_to_trait &= self.predicate_may_hold(&obl); all_returns_conform_to_trait &= self.predicate_may_hold(&obl);
}
} }
} }
} }
} else {
// We still want to verify whether all the return types conform to each other.
for expr in &visitor.0 {
let returned_ty = tables.node_type_opt(expr.hir_id);
all_returns_have_same_type &= last_ty == returned_ty || last_ty.is_none();
last_ty = returned_ty;
}
} }
} else {
// We still want to verify whether all the return types conform to each other.
for expr in &visitor.0 {
let returned_ty = tables.node_type_opt(expr.hir_id);
all_returns_have_same_type &= last_ty == returned_ty || last_ty.is_none();
last_ty = returned_ty;
}
}
let (snippet, last_ty) = let (snippet, last_ty) =
if let (true, hir::TyKind::TraitObject(..), Ok(snippet), true, Some(last_ty)) = ( if let (true, hir::TyKind::TraitObject(..), Ok(snippet), true, Some(last_ty)) = (
// Verify that we're dealing with a return `dyn Trait` // Verify that we're dealing with a return `dyn Trait`
ret_ty.span.overlaps(span), ret_ty.span.overlaps(span),
&ret_ty.kind, &ret_ty.kind,
self.tcx.sess.source_map().span_to_snippet(ret_ty.span), self.tcx.sess.source_map().span_to_snippet(ret_ty.span),
// If any of the return types does not conform to the trait, then we can't // If any of the return types does not conform to the trait, then we can't
// suggest `impl Trait` nor trait objects, it is a type mismatch error. // suggest `impl Trait` nor trait objects, it is a type mismatch error.
all_returns_conform_to_trait, all_returns_conform_to_trait,
last_ty, last_ty,
) { ) {
(snippet, last_ty) (snippet, last_ty)
} else {
return false;
};
err.code(error_code!(E0746));
err.set_primary_message("return type cannot have an unboxed trait object");
err.children.clear();
let impl_trait_msg = "for information on `impl Trait`, see \
<https://doc.rust-lang.org/book/ch10-02-traits.html\
#returning-types-that-implement-traits>";
let trait_obj_msg = "for information on trait objects, see \
<https://doc.rust-lang.org/book/ch17-02-trait-objects.html\
#using-trait-objects-that-allow-for-values-of-different-types>";
let has_dyn = snippet.split_whitespace().next().map_or(false, |s| s == "dyn");
let trait_obj = if has_dyn { &snippet[4..] } else { &snippet[..] };
if all_returns_have_same_type {
// Suggest `-> impl Trait`.
err.span_suggestion(
ret_ty.span,
&format!(
"return `impl {1}` instead, as all return paths are of type `{}`, \
which implements `{1}`",
last_ty, trait_obj,
),
format!("impl {}", trait_obj),
Applicability::MachineApplicable,
);
err.note(impl_trait_msg);
} else { } else {
if is_object_safe { return false;
// Suggest `-> Box<dyn Trait>` and `Box::new(returned_value)`. };
// Get all the return values and collect their span and suggestion. err.code(error_code!(E0746));
let mut suggestions = visitor err.set_primary_message("return type cannot have an unboxed trait object");
.0 err.children.clear();
.iter() let impl_trait_msg = "for information on `impl Trait`, see \
.map(|expr| { <https://doc.rust-lang.org/book/ch10-02-traits.html\
( #returning-types-that-implement-traits>";
expr.span, let trait_obj_msg = "for information on trait objects, see \
format!( <https://doc.rust-lang.org/book/ch17-02-trait-objects.html\
"Box::new({})", #using-trait-objects-that-allow-for-values-of-different-types>";
self.tcx.sess.source_map().span_to_snippet(expr.span).unwrap() let has_dyn = snippet.split_whitespace().next().map_or(false, |s| s == "dyn");
), let trait_obj = if has_dyn { &snippet[4..] } else { &snippet[..] };
) if all_returns_have_same_type {
}) // Suggest `-> impl Trait`.
.collect::<Vec<_>>(); err.span_suggestion(
// Add the suggestion for the return type. ret_ty.span,
suggestions.push(( &format!(
ret_ty.span, "return `impl {1}` instead, as all return paths are of type `{}`, \
format!("Box<{}{}>", if has_dyn { "" } else { "dyn " }, snippet), which implements `{1}`",
)); last_ty, trait_obj,
err.multipart_suggestion( ),
format!("impl {}", trait_obj),
Applicability::MachineApplicable,
);
err.note(impl_trait_msg);
} else {
if is_object_safe {
// Suggest `-> Box<dyn Trait>` and `Box::new(returned_value)`.
// Get all the return values and collect their span and suggestion.
let mut suggestions = visitor
.0
.iter()
.map(|expr| {
(
expr.span,
format!(
"Box::new({})",
self.tcx.sess.source_map().span_to_snippet(expr.span).unwrap()
),
)
})
.collect::<Vec<_>>();
// Add the suggestion for the return type.
suggestions.push((
ret_ty.span,
format!("Box<{}{}>", if has_dyn { "" } else { "dyn " }, snippet),
));
err.multipart_suggestion(
"return a trait object instead", "return a trait object instead",
suggestions, suggestions,
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
); );
} else { } else {
err.note(&format!(
"if trait `{}` was object safe, you could return a trait object",
trait_obj,
));
}
err.note(&format!( err.note(&format!(
"if all the returned values were of the same type you could use \ "if trait `{}` was object safe, you could return a trait object",
`impl {}` as the return type",
trait_obj, trait_obj,
)); ));
err.note(impl_trait_msg);
err.note(trait_obj_msg);
err.note("you can create a new `enum` with a variant for each returned type");
} }
return true; err.note(trait_obj_msg);
err.note(&format!(
"if all the returned values were of the same type you could use \
`impl {}` as the return type",
trait_obj,
));
err.note(impl_trait_msg);
err.note("you can create a new `enum` with a variant for each returned type");
} }
false true
} }
crate fn point_at_returns_when_relevant( crate fn point_at_returns_when_relevant(
@ -1686,6 +1688,8 @@ pub fn suggest_constraining_type_param(
false false
} }
/// Collect all the returned expressions within the input expression.
/// Used to point at the return spans when we want to suggest some change to them.
struct ReturnsVisitor<'v>(Vec<&'v hir::Expr<'v>>); struct ReturnsVisitor<'v>(Vec<&'v hir::Expr<'v>>);
impl<'v> Visitor<'v> for ReturnsVisitor<'v> { impl<'v> Visitor<'v> for ReturnsVisitor<'v> {

View File

@ -1171,7 +1171,7 @@ impl<'tcx> ObligationCause<'tcx> {
} }
} }
impl<'tcx> ObligationCauseCode<'tcx> { impl ObligationCauseCode<'_> {
// Return the base obligation, ignoring derived obligations. // Return the base obligation, ignoring derived obligations.
pub fn peel_derives(&self) -> &Self { pub fn peel_derives(&self) -> &Self {
let mut base_cause = self; let mut base_cause = self;

View File

@ -12,8 +12,8 @@ impl T for S {
fn bar(&self) {} fn bar(&self) {}
} }
// Having the trait `T` as return type is invalid because bare traits do not // Having the trait `T` as return type is invalid because
// have a statically known size: // bare trait objects do not have a statically known size:
fn foo() -> dyn T { fn foo() -> dyn T {
S(42) S(42)
} }
@ -32,15 +32,15 @@ If there is a single type involved, you can use [`impl Trait`]:
# fn bar(&self) {} # fn bar(&self) {}
# } # }
// The compiler will select `S(usize)` as the materialized return type of this // The compiler will select `S(usize)` as the materialized return type of this
// function, but callers will only be able to access associated items from `T`. // function, but callers will only know that the return type implements `T`.
fn foo() -> impl T { fn foo() -> impl T {
S(42) S(42)
} }
``` ```
If there are multiple types involved, the only way you care to interact with If there are multiple types involved, the only way you care to interact with
them is through the trait's interface and having to rely on dynamic dispatch is them is through the trait's interface, and having to rely on dynamic dispatch
acceptable, then you can use [trait objects] with `Box`, or other container is acceptable, then you can use [trait objects] with `Box`, or other container
types like `Rc` or `Arc`: types like `Rc` or `Arc`:
``` ```

View File

@ -68,7 +68,7 @@ use rustc_error_codes::*;
use rustc_errors::{struct_span_err, DiagnosticBuilder}; use rustc_errors::{struct_span_err, DiagnosticBuilder};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_span; use rustc_span::{self, Span};
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
use rustc_target::spec::abi::Abi; use rustc_target::spec::abi::Abi;
use smallvec::{smallvec, SmallVec}; use smallvec::{smallvec, SmallVec};
@ -1352,41 +1352,50 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
} }
} }
if let (Some(sp), Some(return_sp)) = (fcx.ret_coercion_span.borrow().as_ref(), return_sp) { if let (Some(sp), Some(return_sp)) = (fcx.ret_coercion_span.borrow().as_ref(), return_sp) {
err.span_label(return_sp, "expected because this return type..."); self.add_impl_trait_explanation(&mut err, fcx, expected, *sp, return_sp);
err.span_label( *sp, format!(
"...is found to be `{}` here",
fcx.resolve_vars_with_obligations(expected),
));
err.note("to return `impl Trait`, all returned values must be of the same type");
let snippet = fcx
.tcx
.sess
.source_map()
.span_to_snippet(return_sp)
.unwrap_or_else(|_| "dyn Trait".to_string());
let mut snippet_iter = snippet.split_whitespace();
let has_impl = snippet_iter.next().map_or(false, |s| s == "impl");
if has_impl {
err.help(&format!(
"you can instead return a trait object using `Box<dyn {}>`",
&snippet[5..]
));
}
err.help("alternatively, create a new `enum` with a variant for each returned type");
let impl_trait_msg = "for information on `impl Trait`, see \
<https://doc.rust-lang.org/book/ch10-02-traits.html\
#returning-types-that-implement-traits>";
let trait_obj_msg = "for information on trait objects, see \
<https://doc.rust-lang.org/book/ch17-02-trait-objects.html\
#using-trait-objects-that-allow-for-values-of-different-types>";
err.note(impl_trait_msg);
if has_impl {
err.note(trait_obj_msg);
}
} }
err err
} }
fn add_impl_trait_explanation<'a>(
&self,
err: &mut DiagnosticBuilder<'a>,
fcx: &FnCtxt<'a, 'tcx>,
expected: Ty<'tcx>,
sp: Span,
return_sp: Span,
) {
err.span_label(return_sp, "expected because this return type...");
err.span_label(
sp,
format!("...is found to be `{}` here", fcx.resolve_vars_with_obligations(expected)),
);
let impl_trait_msg = "for information on `impl Trait`, see \
<https://doc.rust-lang.org/book/ch10-02-traits.html\
#returning-types-that-implement-traits>";
let trait_obj_msg = "for information on trait objects, see \
<https://doc.rust-lang.org/book/ch17-02-trait-objects.html\
#using-trait-objects-that-allow-for-values-of-different-types>";
err.note("to return `impl Trait`, all returned values must be of the same type");
err.note(impl_trait_msg);
let snippet = fcx
.tcx
.sess
.source_map()
.span_to_snippet(return_sp)
.unwrap_or_else(|_| "dyn Trait".to_string());
let mut snippet_iter = snippet.split_whitespace();
let has_impl = snippet_iter.next().map_or(false, |s| s == "impl");
if has_impl {
err.help(&format!(
"you can instead return a trait object using `Box<dyn {}>`",
&snippet[5..]
));
err.note(trait_obj_msg);
}
err.help("alternatively, create a new `enum` with a variant for each returned type");
}
fn is_return_ty_unsized(&self, fcx: &FnCtxt<'a, 'tcx>, blk_id: hir::HirId) -> bool { fn is_return_ty_unsized(&self, fcx: &FnCtxt<'a, 'tcx>, blk_id: hir::HirId) -> bool {
if let Some((fn_decl, _)) = fcx.get_fn_decl(blk_id) { if let Some((fn_decl, _)) = fcx.get_fn_decl(blk_id) {
if let hir::FunctionRetTy::Return(ty) = fn_decl.output { if let hir::FunctionRetTy::Return(ty) = fn_decl.output {

View File

@ -82,11 +82,18 @@ error[E0746]: return type cannot have an unboxed trait object
LL | fn bal() -> dyn Trait { LL | fn bal() -> dyn Trait {
| ^^^^^^^^^ doesn't have a size known at compile-time | ^^^^^^^^^ doesn't have a size known at compile-time
| |
= note: if trait `Trait` was object safe, you could return a trait object = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
= note: if all the returned values were of the same type you could use `impl Trait` as the return type = note: if all the returned values were of the same type you could use `impl Trait` as the return type
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits> = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
= note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
= note: you can create a new `enum` with a variant for each returned type = note: you can create a new `enum` with a variant for each returned type
help: return a trait object instead
|
LL | fn bal() -> Box<dyn Trait> {
LL | if true {
LL | return Box::new(Struct);
LL | }
LL | Box::new(42)
|
error[E0746]: return type cannot have an unboxed trait object error[E0746]: return type cannot have an unboxed trait object
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:27:13 --> $DIR/dyn-trait-return-should-be-impl-trait.rs:27:13

View File

@ -11,10 +11,10 @@ LL | 0_u32
| ^^^^^ expected `i32`, found `u32` | ^^^^^ expected `i32`, found `u32`
| |
= note: to return `impl Trait`, all returned values must be of the same type = note: to return `impl Trait`, all returned values must be of the same type
= help: you can instead return a trait object using `Box<dyn Foo>`
= help: alternatively, create a new `enum` with a variant for each returned type
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits> = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
= help: you can instead return a trait object using `Box<dyn Foo>`
= note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types> = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
= help: alternatively, create a new `enum` with a variant for each returned type
error[E0277]: cannot add `impl Foo` to `u32` error[E0277]: cannot add `impl Foo` to `u32`
--> $DIR/equality.rs:24:11 --> $DIR/equality.rs:24:11

View File

@ -11,10 +11,10 @@ LL | 1u32
| ^^^^ expected `i32`, found `u32` | ^^^^ expected `i32`, found `u32`
| |
= note: to return `impl Trait`, all returned values must be of the same type = note: to return `impl Trait`, all returned values must be of the same type
= help: you can instead return a trait object using `Box<dyn std::fmt::Display>`
= help: alternatively, create a new `enum` with a variant for each returned type
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits> = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
= help: you can instead return a trait object using `Box<dyn std::fmt::Display>`
= note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types> = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
= help: alternatively, create a new `enum` with a variant for each returned type
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:13:16 --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:13:16
@ -29,10 +29,10 @@ LL | return 1u32;
| ^^^^ expected `i32`, found `u32` | ^^^^ expected `i32`, found `u32`
| |
= note: to return `impl Trait`, all returned values must be of the same type = note: to return `impl Trait`, all returned values must be of the same type
= help: you can instead return a trait object using `Box<dyn std::fmt::Display>`
= help: alternatively, create a new `enum` with a variant for each returned type
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits> = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
= help: you can instead return a trait object using `Box<dyn std::fmt::Display>`
= note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types> = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
= help: alternatively, create a new `enum` with a variant for each returned type
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:22:9 --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:22:9
@ -47,10 +47,10 @@ LL | 1u32
| ^^^^ expected `i32`, found `u32` | ^^^^ expected `i32`, found `u32`
| |
= note: to return `impl Trait`, all returned values must be of the same type = note: to return `impl Trait`, all returned values must be of the same type
= help: you can instead return a trait object using `Box<dyn std::fmt::Display>`
= help: alternatively, create a new `enum` with a variant for each returned type
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits> = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
= help: you can instead return a trait object using `Box<dyn std::fmt::Display>`
= note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types> = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
= help: alternatively, create a new `enum` with a variant for each returned type
error[E0308]: `if` and `else` have incompatible types error[E0308]: `if` and `else` have incompatible types
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:31:9 --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:31:9
@ -77,10 +77,10 @@ LL | _ => 1u32,
| ^^^^ expected `i32`, found `u32` | ^^^^ expected `i32`, found `u32`
| |
= note: to return `impl Trait`, all returned values must be of the same type = note: to return `impl Trait`, all returned values must be of the same type
= help: you can instead return a trait object using `Box<dyn std::fmt::Display>`
= help: alternatively, create a new `enum` with a variant for each returned type
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits> = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
= help: you can instead return a trait object using `Box<dyn std::fmt::Display>`
= note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types> = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
= help: alternatively, create a new `enum` with a variant for each returned type
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:45:5 --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:45:5
@ -97,10 +97,10 @@ LL | | }
| |_____^ expected `i32`, found `u32` | |_____^ expected `i32`, found `u32`
| |
= note: to return `impl Trait`, all returned values must be of the same type = note: to return `impl Trait`, all returned values must be of the same type
= help: you can instead return a trait object using `Box<dyn std::fmt::Display>`
= help: alternatively, create a new `enum` with a variant for each returned type
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits> = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
= help: you can instead return a trait object using `Box<dyn std::fmt::Display>`
= note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types> = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
= help: alternatively, create a new `enum` with a variant for each returned type
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:59:13 --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:59:13
@ -115,10 +115,10 @@ LL | 1u32
| ^^^^ expected `i32`, found `u32` | ^^^^ expected `i32`, found `u32`
| |
= note: to return `impl Trait`, all returned values must be of the same type = note: to return `impl Trait`, all returned values must be of the same type
= help: you can instead return a trait object using `Box<dyn std::fmt::Display>`
= help: alternatively, create a new `enum` with a variant for each returned type
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits> = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
= help: you can instead return a trait object using `Box<dyn std::fmt::Display>`
= note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types> = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
= help: alternatively, create a new `enum` with a variant for each returned type
error: aborting due to 7 previous errors error: aborting due to 7 previous errors