Skip to content

Commit

Permalink
Auto merge of rust-lang#13433 - rust-lang:revert-13354-try-stuff, r=V…
Browse files Browse the repository at this point in the history
…eykril

Revert "feat: Diagnose some incorrect usages of the question mark operator"

Reverts rust-lang/rust-analyzer#13354

It seems like we are getting stuck with inference variables here, not just placeholders and errors so there is probably more wrong here that I don't understand. Reverting seems like the best solution right now as I don't have the time to look into this this week.
  • Loading branch information
bors committed Oct 18, 2022
2 parents 4d4c05d + 8047512 commit 97b357e
Show file tree
Hide file tree
Showing 13 changed files with 125 additions and 289 deletions.
1 change: 0 additions & 1 deletion crates/hir-expand/src/mod_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,6 @@ macro_rules! __known_path {
(core::future::Future) => {};
(core::future::IntoFuture) => {};
(core::ops::Try) => {};
(core::ops::FromResidual) => {};
($path:path) => {
compile_error!("Please register your known path in the path module")
};
Expand Down
2 changes: 0 additions & 2 deletions crates/hir-expand/src/name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,8 +279,6 @@ pub mod known {
RangeToInclusive,
RangeTo,
Range,
Residual,
FromResidual,
Neg,
Not,
None,
Expand Down
13 changes: 11 additions & 2 deletions crates/hir-ty/src/infer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,7 @@ pub(crate) type InferResult<T> = Result<InferOk<T>, TypeError>;
pub enum InferenceDiagnostic {
NoSuchField { expr: ExprId },
BreakOutsideOfLoop { expr: ExprId, is_break: bool },
IncorrectTryTarget { expr: ExprId },
MismatchedArgCount { call_expr: ExprId, expected: usize, found: usize },
DoesNotImplement { expr: ExprId, trait_: TraitId, ty: Ty },
}

/// A mismatch between an expected and an inferred type.
Expand Down Expand Up @@ -907,6 +905,17 @@ impl<'a> InferenceContext<'a> {
self.db.trait_data(trait_).associated_type_by_name(&name![Item])
}

fn resolve_ops_try_ok(&self) -> Option<TypeAliasId> {
// FIXME resolve via lang_item once try v2 is stable
let path = path![core::ops::Try];
let trait_ = self.resolver.resolve_known_trait(self.db.upcast(), &path)?;
let trait_data = self.db.trait_data(trait_);
trait_data
// FIXME remove once try v2 is stable
.associated_type_by_name(&name![Ok])
.or_else(|| trait_data.associated_type_by_name(&name![Output]))
}

fn resolve_ops_neg_output(&self) -> Option<TypeAliasId> {
let trait_ = self.resolve_lang_item(name![neg])?.as_trait()?;
self.db.trait_data(trait_).associated_type_by_name(&name![Output])
Expand Down
99 changes: 8 additions & 91 deletions crates/hir-ty/src/infer/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,24 @@ use hir_def::{
resolver::resolver_for_expr,
ConstParamId, FieldId, ItemContainerId, Lookup,
};
use hir_expand::{name, name::Name};
use hir_expand::name::Name;
use stdx::always;
use syntax::ast::RangeOp;

use crate::{
autoderef::{self, Autoderef},
consteval,
infer::{coerce::CoerceMany, find_continuable, path, BreakableKind},
infer::{coerce::CoerceMany, find_continuable, BreakableKind},
lower::{
const_or_path_to_chalk, generic_arg_to_chalk, lower_to_chalk_mutability, ParamLoweringMode,
},
mapping::{from_chalk, ToChalk},
method_resolution::{self, lang_names_for_bin_op, VisibleFromModule},
primitive::{self, UintTy},
static_lifetime, to_assoc_type_id, to_chalk_trait_id,
static_lifetime, to_chalk_trait_id,
utils::{generics, Generics},
AdtId, AliasEq, AliasTy, Binders, CallableDefId, FnPointer, FnSig, FnSubst, Interner,
ProjectionTy, Rawness, Scalar, Substitution, TraitRef, Ty, TyBuilder, TyExt, TyKind,
AdtId, Binders, CallableDefId, FnPointer, FnSig, FnSubst, Interner, Rawness, Scalar,
Substitution, TraitRef, Ty, TyBuilder, TyExt, TyKind,
};

use super::{
Expand Down Expand Up @@ -564,29 +564,9 @@ impl<'a> InferenceContext<'a> {
let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
self.resolve_associated_type(inner_ty, self.resolve_future_future_output())
}
&Expr::Try { expr } => {
let inner_ty = self.infer_expr_inner(expr, &Expectation::none());
match self.resolve_try_impl_for(inner_ty.clone()) {
Some((_, Some((output, residual)))) => {
if let Some((_trait, false)) =
self.implements_from_residual(self.return_ty.clone(), residual)
{
self.push_diagnostic(InferenceDiagnostic::IncorrectTryTarget {
expr: tgt_expr,
});
}
output
}
Some((trait_, None)) => {
self.push_diagnostic(InferenceDiagnostic::DoesNotImplement {
expr,
trait_,
ty: inner_ty,
});
self.err_ty()
}
None => self.err_ty(),
}
Expr::Try { expr } => {
let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
self.resolve_associated_type(inner_ty, self.resolve_ops_try_ok())
}
Expr::Cast { expr, type_ref } => {
// FIXME: propagate the "castable to" expectation (and find a test case that shows this is necessary)
Expand Down Expand Up @@ -1550,67 +1530,4 @@ impl<'a> InferenceContext<'a> {
let ctx = self.breakables.pop().expect("breakable stack broken");
(ctx.may_break.then(|| ctx.coerce.complete()), res)
}

/// Check whether `ty` implements `FromResidual<r>`
fn implements_from_residual(&mut self, ty: Ty, r: Ty) -> Option<(hir_def::TraitId, bool)> {
let from_residual_trait = self
.resolver
.resolve_known_trait(self.db.upcast(), &(super::path![core::ops::FromResidual]))?;
let r = GenericArgData::Ty(r).intern(Interner);
let b = TyBuilder::trait_ref(self.db, from_residual_trait);
if b.remaining() != 2 {
return Some((from_residual_trait, false));
}
let trait_ref = b.push(ty).push(r).build();
Some((from_residual_trait, self.table.try_obligation(trait_ref.cast(Interner)).is_some()))
}

fn resolve_try_impl_for(&mut self, ty: Ty) -> Option<(hir_def::TraitId, Option<(Ty, Ty)>)> {
let path = path![core::ops::Try];
let trait_ = self.resolver.resolve_known_trait(self.db.upcast(), &path)?;

let trait_ref = TyBuilder::trait_ref(self.db, trait_).push(ty).build();
let substitution = trait_ref.substitution.clone();
self.push_obligation(trait_ref.clone().cast(Interner));

let trait_data = self.db.trait_data(trait_);
let output = trait_data.associated_type_by_name(&name![Output]);
let residual = trait_data.associated_type_by_name(&name![Residual]);

let output_ty = match output {
Some(output) => {
let output_ty = self.table.new_type_var();
let alias_eq = AliasEq {
alias: AliasTy::Projection(ProjectionTy {
associated_ty_id: to_assoc_type_id(output),
substitution: substitution.clone(),
}),
ty: output_ty.clone(),
};
self.push_obligation(alias_eq.cast(Interner));
output_ty
}
None => self.err_ty(),
};
let residual_ty = match residual {
Some(residual) => {
let residual_ty = self.table.new_type_var();
let alias_eq = AliasEq {
alias: AliasTy::Projection(ProjectionTy {
associated_ty_id: to_assoc_type_id(residual),
substitution,
}),
ty: residual_ty.clone(),
};
self.push_obligation(alias_eq.cast(Interner));
residual_ty
}
None => self.err_ty(),
};
// FIXME: We are doing the work twice here I think?
Some((
trait_,
self.table.try_obligation(trait_ref.cast(Interner)).map(|_| (output_ty, residual_ty)),
))
}
}
18 changes: 0 additions & 18 deletions crates/hir-ty/src/method_resolution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1111,24 +1111,6 @@ pub fn resolve_indexing_op(
}
None
}
/// Returns the receiver type for the try branch trait call.
pub fn resolve_branch_op(
db: &dyn HirDatabase,
env: Arc<TraitEnvironment>,
ty: Canonical<Ty>,
try_trait: TraitId,
) -> Option<ReceiverAdjustments> {
let mut table = InferenceTable::new(db, env.clone());
let ty = table.instantiate_canonical(ty);
let (deref_chain, adj) = autoderef_method_receiver(&mut table, ty);
for (ty, adj) in deref_chain.into_iter().zip(adj) {
let goal = generic_implements_goal(db, env.clone(), try_trait, &ty);
if db.trait_solve(env.krate, goal.cast(Interner)).is_some() {
return Some(adj);
}
}
None
}

macro_rules! check_that {
($cond:expr) => {
Expand Down
92 changes: 87 additions & 5 deletions crates/hir-ty/src/tests/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,16 +162,98 @@ fn test() {
);
}

#[test]
fn infer_try() {
check_types(
r#"
//- /main.rs crate:main deps:core
fn test() {
let r: Result<i32, u64> = Result::Ok(1);
let v = r?;
v;
} //^ i32
//- /core.rs crate:core
pub mod ops {
pub trait Try {
type Ok;
type Error;
}
}
pub mod result {
pub enum Result<O, E> {
Ok(O),
Err(E)
}
impl<O, E> crate::ops::Try for Result<O, E> {
type Ok = O;
type Error = E;
}
}
pub mod prelude {
pub mod rust_2018 {
pub use crate::{result::*, ops::*};
}
}
"#,
);
}

#[test]
fn infer_try_trait_v2() {
check_types(
r#"
//- minicore: try
fn test() -> core::ops::ControlFlow<u32, f32> {
let r: core::ops::ControlFlow<u32, f32> = core::ops::ControlFlow::Continue(1.0);
//- /main.rs crate:main deps:core
fn test() {
let r: Result<i32, u64> = Result::Ok(1);
let v = r?;
//^ f32
r
v;
} //^ i32
//- /core.rs crate:core
mod ops {
mod try_trait {
pub trait Try: FromResidual {
type Output;
type Residual;
}
pub trait FromResidual<R = <Self as Try>::Residual> {}
}
pub use self::try_trait::FromResidual;
pub use self::try_trait::Try;
}
mod convert {
pub trait From<T> {}
impl<T> From<T> for T {}
}
pub mod result {
use crate::convert::From;
use crate::ops::{Try, FromResidual};
pub enum Infallible {}
pub enum Result<O, E> {
Ok(O),
Err(E)
}
impl<O, E> Try for Result<O, E> {
type Output = O;
type Error = Result<Infallible, E>;
}
impl<T, E, F: From<E>> FromResidual<Result<Infallible, E>> for Result<T, F> {}
}
pub mod prelude {
pub mod rust_2018 {
pub use crate::result::*;
}
}
"#,
);
Expand Down
14 changes: 1 addition & 13 deletions crates/hir/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
use base_db::CrateId;
use cfg::{CfgExpr, CfgOptions};
use either::Either;
use hir_def::{path::ModPath, TraitId};
use hir_def::path::ModPath;
use hir_expand::{name::Name, HirFileId, InFile};
use syntax::{ast, AstPtr, SyntaxNodePtr, TextRange};

Expand All @@ -33,15 +33,13 @@ diagnostics![
BreakOutsideOfLoop,
InactiveCode,
IncorrectCase,
IncorrectTryExpr,
InvalidDeriveTarget,
MacroError,
MalformedDerive,
MismatchedArgCount,
MissingFields,
MissingMatchArms,
MissingUnsafe,
NotImplemented,
NoSuchField,
ReplaceFilterMapNextWithFindMap,
TypeMismatch,
Expand Down Expand Up @@ -155,16 +153,6 @@ pub struct MismatchedArgCount {
pub expected: usize,
pub found: usize,
}
#[derive(Debug)]
pub struct IncorrectTryExpr {
pub expr: InFile<AstPtr<ast::Expr>>,
}
#[derive(Debug)]
pub struct NotImplemented {
pub expr: InFile<AstPtr<ast::Expr>>,
pub trait_: TraitId,
pub ty: Type,
}

#[derive(Debug)]
pub struct MissingMatchArms {
Expand Down
Loading

0 comments on commit 97b357e

Please sign in to comment.