diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-01-19 18:03:36 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-01-19 18:03:36 +0000 |
commit | 1c296d54e3dcc36c1a778873f26035000a352ba2 (patch) | |
tree | 0a6ce660ee32080287284c93bffaaaada91f3584 /crates/ra_hir/src/ty.rs | |
parent | bade91db081a3465dea3547ab8ab669f78fde9dc (diff) | |
parent | 5f3509e140d19b989db418a00ac6778c622cde5d (diff) |
Merge #576
576: Beginnings of generics r=matklad a=flodiebold
This implements the beginnings of the generics infrastructure; generic parameters for structs work and are correctly substituted in fields. Functions and methods aren't handled at all yet (as the tests show).
The name resolution in `ty` really needs refactoring now, I hope to do that next ;)
Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r-- | crates/ra_hir/src/ty.rs | 370 |
1 files changed, 308 insertions, 62 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 8d6493887..9b7182485 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -37,6 +37,8 @@ use crate::{ | |||
37 | type_ref::{TypeRef, Mutability}, | 37 | type_ref::{TypeRef, Mutability}, |
38 | name::KnownName, | 38 | name::KnownName, |
39 | expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat}, | 39 | expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat}, |
40 | generics::GenericParams, | ||
41 | path::GenericArg, | ||
40 | }; | 42 | }; |
41 | 43 | ||
42 | /// The ID of a type variable. | 44 | /// The ID of a type variable. |
@@ -151,10 +153,20 @@ impl Expectation { | |||
151 | } | 153 | } |
152 | } | 154 | } |
153 | 155 | ||
156 | /// A list of substitutions for generic parameters. | ||
157 | #[derive(Clone, PartialEq, Eq, Debug)] | ||
158 | pub struct Substs(Arc<[Ty]>); | ||
159 | |||
160 | impl Substs { | ||
161 | pub fn empty() -> Substs { | ||
162 | Substs(Arc::new([])) | ||
163 | } | ||
164 | } | ||
165 | |||
154 | /// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs). | 166 | /// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs). |
155 | /// | 167 | /// |
156 | /// This should be cheap to clone. | 168 | /// This should be cheap to clone. |
157 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] | 169 | #[derive(Clone, PartialEq, Eq, Debug)] |
158 | pub enum Ty { | 170 | pub enum Ty { |
159 | /// The primitive boolean type. Written as `bool`. | 171 | /// The primitive boolean type. Written as `bool`. |
160 | Bool, | 172 | Bool, |
@@ -175,7 +187,8 @@ pub enum Ty { | |||
175 | def_id: DefId, | 187 | def_id: DefId, |
176 | /// The name, for displaying. | 188 | /// The name, for displaying. |
177 | name: Name, | 189 | name: Name, |
178 | // later we'll need generic substitutions here | 190 | /// Substitutions for the generic parameters of the type. |
191 | substs: Substs, | ||
179 | }, | 192 | }, |
180 | 193 | ||
181 | /// The pointee of a string slice. Written as `str`. | 194 | /// The pointee of a string slice. Written as `str`. |
@@ -234,9 +247,15 @@ pub enum Ty { | |||
234 | 247 | ||
235 | // Opaque (`impl Trait`) type found in a return type. | 248 | // Opaque (`impl Trait`) type found in a return type. |
236 | // Opaque(DefId, Substs), | 249 | // Opaque(DefId, Substs), |
250 | /// A type parameter; for example, `T` in `fn f<T>(x: T) {} | ||
251 | Param { | ||
252 | /// The index of the parameter (starting with parameters from the | ||
253 | /// surrounding impl, then the current function). | ||
254 | idx: u32, | ||
255 | /// The name of the parameter, for displaying. | ||
256 | name: Name, | ||
257 | }, | ||
237 | 258 | ||
238 | // A type parameter; for example, `T` in `fn f<T>(x: T) {} | ||
239 | // Param(ParamTy), | ||
240 | /// A type variable used during type checking. Not to be confused with a | 259 | /// A type variable used during type checking. Not to be confused with a |
241 | /// type parameter. | 260 | /// type parameter. |
242 | Infer(InferTy), | 261 | Infer(InferTy), |
@@ -250,7 +269,7 @@ pub enum Ty { | |||
250 | } | 269 | } |
251 | 270 | ||
252 | /// A function signature. | 271 | /// A function signature. |
253 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] | 272 | #[derive(Clone, PartialEq, Eq, Debug)] |
254 | pub struct FnSig { | 273 | pub struct FnSig { |
255 | input: Vec<Ty>, | 274 | input: Vec<Ty>, |
256 | output: Ty, | 275 | output: Ty, |
@@ -259,8 +278,12 @@ pub struct FnSig { | |||
259 | impl Ty { | 278 | impl Ty { |
260 | pub(crate) fn from_hir( | 279 | pub(crate) fn from_hir( |
261 | db: &impl HirDatabase, | 280 | db: &impl HirDatabase, |
281 | // TODO: the next three parameters basically describe the scope for name | ||
282 | // resolution; this should be refactored into something like a general | ||
283 | // resolver architecture | ||
262 | module: &Module, | 284 | module: &Module, |
263 | impl_block: Option<&ImplBlock>, | 285 | impl_block: Option<&ImplBlock>, |
286 | generics: &GenericParams, | ||
264 | type_ref: &TypeRef, | 287 | type_ref: &TypeRef, |
265 | ) -> Self { | 288 | ) -> Self { |
266 | match type_ref { | 289 | match type_ref { |
@@ -268,32 +291,32 @@ impl Ty { | |||
268 | TypeRef::Tuple(inner) => { | 291 | TypeRef::Tuple(inner) => { |
269 | let inner_tys = inner | 292 | let inner_tys = inner |
270 | .iter() | 293 | .iter() |
271 | .map(|tr| Ty::from_hir(db, module, impl_block, tr)) | 294 | .map(|tr| Ty::from_hir(db, module, impl_block, generics, tr)) |
272 | .collect::<Vec<_>>(); | 295 | .collect::<Vec<_>>(); |
273 | Ty::Tuple(inner_tys.into()) | 296 | Ty::Tuple(inner_tys.into()) |
274 | } | 297 | } |
275 | TypeRef::Path(path) => Ty::from_hir_path(db, module, impl_block, path), | 298 | TypeRef::Path(path) => Ty::from_hir_path(db, module, impl_block, generics, path), |
276 | TypeRef::RawPtr(inner, mutability) => { | 299 | TypeRef::RawPtr(inner, mutability) => { |
277 | let inner_ty = Ty::from_hir(db, module, impl_block, inner); | 300 | let inner_ty = Ty::from_hir(db, module, impl_block, generics, inner); |
278 | Ty::RawPtr(Arc::new(inner_ty), *mutability) | 301 | Ty::RawPtr(Arc::new(inner_ty), *mutability) |
279 | } | 302 | } |
280 | TypeRef::Array(inner) => { | 303 | TypeRef::Array(inner) => { |
281 | let inner_ty = Ty::from_hir(db, module, impl_block, inner); | 304 | let inner_ty = Ty::from_hir(db, module, impl_block, generics, inner); |
282 | Ty::Array(Arc::new(inner_ty)) | 305 | Ty::Array(Arc::new(inner_ty)) |
283 | } | 306 | } |
284 | TypeRef::Slice(inner) => { | 307 | TypeRef::Slice(inner) => { |
285 | let inner_ty = Ty::from_hir(db, module, impl_block, inner); | 308 | let inner_ty = Ty::from_hir(db, module, impl_block, generics, inner); |
286 | Ty::Slice(Arc::new(inner_ty)) | 309 | Ty::Slice(Arc::new(inner_ty)) |
287 | } | 310 | } |
288 | TypeRef::Reference(inner, mutability) => { | 311 | TypeRef::Reference(inner, mutability) => { |
289 | let inner_ty = Ty::from_hir(db, module, impl_block, inner); | 312 | let inner_ty = Ty::from_hir(db, module, impl_block, generics, inner); |
290 | Ty::Ref(Arc::new(inner_ty), *mutability) | 313 | Ty::Ref(Arc::new(inner_ty), *mutability) |
291 | } | 314 | } |
292 | TypeRef::Placeholder => Ty::Unknown, | 315 | TypeRef::Placeholder => Ty::Unknown, |
293 | TypeRef::Fn(params) => { | 316 | TypeRef::Fn(params) => { |
294 | let mut inner_tys = params | 317 | let mut inner_tys = params |
295 | .iter() | 318 | .iter() |
296 | .map(|tr| Ty::from_hir(db, module, impl_block, tr)) | 319 | .map(|tr| Ty::from_hir(db, module, impl_block, generics, tr)) |
297 | .collect::<Vec<_>>(); | 320 | .collect::<Vec<_>>(); |
298 | let return_ty = inner_tys | 321 | let return_ty = inner_tys |
299 | .pop() | 322 | .pop() |
@@ -312,15 +335,19 @@ impl Ty { | |||
312 | db: &impl HirDatabase, | 335 | db: &impl HirDatabase, |
313 | module: &Module, | 336 | module: &Module, |
314 | impl_block: Option<&ImplBlock>, | 337 | impl_block: Option<&ImplBlock>, |
338 | generics: &GenericParams, | ||
315 | type_ref: Option<&TypeRef>, | 339 | type_ref: Option<&TypeRef>, |
316 | ) -> Self { | 340 | ) -> Self { |
317 | type_ref.map_or(Ty::Unknown, |t| Ty::from_hir(db, module, impl_block, t)) | 341 | type_ref.map_or(Ty::Unknown, |t| { |
342 | Ty::from_hir(db, module, impl_block, generics, t) | ||
343 | }) | ||
318 | } | 344 | } |
319 | 345 | ||
320 | pub(crate) fn from_hir_path( | 346 | pub(crate) fn from_hir_path( |
321 | db: &impl HirDatabase, | 347 | db: &impl HirDatabase, |
322 | module: &Module, | 348 | module: &Module, |
323 | impl_block: Option<&ImplBlock>, | 349 | impl_block: Option<&ImplBlock>, |
350 | generics: &GenericParams, | ||
324 | path: &Path, | 351 | path: &Path, |
325 | ) -> Self { | 352 | ) -> Self { |
326 | if let Some(name) = path.as_ident() { | 353 | if let Some(name) = path.as_ident() { |
@@ -329,7 +356,15 @@ impl Ty { | |||
329 | } else if let Some(float_ty) = primitive::UncertainFloatTy::from_name(name) { | 356 | } else if let Some(float_ty) = primitive::UncertainFloatTy::from_name(name) { |
330 | return Ty::Float(float_ty); | 357 | return Ty::Float(float_ty); |
331 | } else if name.as_known_name() == Some(KnownName::SelfType) { | 358 | } else if name.as_known_name() == Some(KnownName::SelfType) { |
332 | return Ty::from_hir_opt(db, module, None, impl_block.map(|i| i.target_type())); | 359 | // TODO pass the impl block's generics? |
360 | let generics = &GenericParams::default(); | ||
361 | return Ty::from_hir_opt( | ||
362 | db, | ||
363 | module, | ||
364 | None, | ||
365 | generics, | ||
366 | impl_block.map(|i| i.target_type()), | ||
367 | ); | ||
333 | } else if let Some(known) = name.as_known_name() { | 368 | } else if let Some(known) = name.as_known_name() { |
334 | match known { | 369 | match known { |
335 | KnownName::Bool => return Ty::Bool, | 370 | KnownName::Bool => return Ty::Bool, |
@@ -337,16 +372,89 @@ impl Ty { | |||
337 | KnownName::Str => return Ty::Str, | 372 | KnownName::Str => return Ty::Str, |
338 | _ => {} | 373 | _ => {} |
339 | } | 374 | } |
375 | } else if let Some(generic_param) = generics.find_by_name(&name) { | ||
376 | return Ty::Param { | ||
377 | idx: generic_param.idx, | ||
378 | name: generic_param.name.clone(), | ||
379 | }; | ||
340 | } | 380 | } |
341 | } | 381 | } |
342 | 382 | ||
343 | // Resolve in module (in type namespace) | 383 | // Resolve in module (in type namespace) |
344 | let resolved = if let Some(r) = module.resolve_path(db, path).take_types() { | 384 | let resolved = match module.resolve_path(db, path).take_types() { |
345 | r | 385 | Some(r) => r, |
346 | } else { | 386 | None => return Ty::Unknown, |
347 | return Ty::Unknown; | ||
348 | }; | 387 | }; |
349 | db.type_for_def(resolved) | 388 | let ty = db.type_for_def(resolved); |
389 | let substs = Ty::substs_from_path(db, module, impl_block, generics, path, resolved); | ||
390 | ty.apply_substs(substs) | ||
391 | } | ||
392 | |||
393 | /// Collect generic arguments from a path into a `Substs`. See also | ||
394 | /// `create_substs_for_ast_path` and `def_to_ty` in rustc. | ||
395 | fn substs_from_path( | ||
396 | db: &impl HirDatabase, | ||
397 | // the scope of the segment... | ||
398 | module: &Module, | ||
399 | impl_block: Option<&ImplBlock>, | ||
400 | outer_generics: &GenericParams, | ||
401 | path: &Path, | ||
402 | resolved: DefId, | ||
403 | ) -> Substs { | ||
404 | let mut substs = Vec::new(); | ||
405 | let def = resolved.resolve(db); | ||
406 | let last = path | ||
407 | .segments | ||
408 | .last() | ||
409 | .expect("path should have at least one segment"); | ||
410 | let (def_generics, segment) = match def { | ||
411 | Def::Struct(s) => (s.generic_params(db), last), | ||
412 | Def::Enum(e) => (e.generic_params(db), last), | ||
413 | Def::Function(f) => (f.generic_params(db), last), | ||
414 | Def::Trait(t) => (t.generic_params(db), last), | ||
415 | Def::EnumVariant(ev) => { | ||
416 | // the generic args for an enum variant may be either specified | ||
417 | // on the segment referring to the enum, or on the segment | ||
418 | // referring to the variant. So `Option::<T>::None` and | ||
419 | // `Option::None::<T>` are both allowed (though the former is | ||
420 | // preferred). See also `def_ids_for_path_segments` in rustc. | ||
421 | let len = path.segments.len(); | ||
422 | let segment = if len >= 2 && path.segments[len - 2].args_and_bindings.is_some() { | ||
423 | // Option::<T>::None | ||
424 | &path.segments[len - 2] | ||
425 | } else { | ||
426 | // Option::None::<T> | ||
427 | last | ||
428 | }; | ||
429 | (ev.parent_enum(db).generic_params(db), segment) | ||
430 | } | ||
431 | _ => return Substs::empty(), | ||
432 | }; | ||
433 | // substs_from_path | ||
434 | if let Some(generic_args) = &segment.args_and_bindings { | ||
435 | // if args are provided, it should be all of them, but we can't rely on that | ||
436 | let param_count = def_generics.params.len(); | ||
437 | for arg in generic_args.args.iter().take(param_count) { | ||
438 | match arg { | ||
439 | GenericArg::Type(type_ref) => { | ||
440 | let ty = Ty::from_hir(db, module, impl_block, outer_generics, type_ref); | ||
441 | substs.push(ty); | ||
442 | } | ||
443 | } | ||
444 | } | ||
445 | } | ||
446 | // add placeholders for args that were not provided | ||
447 | // TODO: handle defaults | ||
448 | for _ in segment | ||
449 | .args_and_bindings | ||
450 | .as_ref() | ||
451 | .map(|ga| ga.args.len()) | ||
452 | .unwrap_or(0)..def_generics.params.len() | ||
453 | { | ||
454 | substs.push(Ty::Unknown); | ||
455 | } | ||
456 | assert_eq!(substs.len(), def_generics.params.len()); | ||
457 | Substs(substs.into()) | ||
350 | } | 458 | } |
351 | 459 | ||
352 | pub fn unit() -> Self { | 460 | pub fn unit() -> Self { |
@@ -374,7 +482,14 @@ impl Ty { | |||
374 | } | 482 | } |
375 | sig_mut.output.walk_mut(f); | 483 | sig_mut.output.walk_mut(f); |
376 | } | 484 | } |
377 | Ty::Adt { .. } => {} // need to walk type parameters later | 485 | Ty::Adt { substs, .. } => { |
486 | // Without an Arc::make_mut_slice, we can't avoid the clone here: | ||
487 | let mut v: Vec<_> = substs.0.iter().cloned().collect(); | ||
488 | for t in &mut v { | ||
489 | t.walk_mut(f); | ||
490 | } | ||
491 | substs.0 = v.into(); | ||
492 | } | ||
378 | _ => {} | 493 | _ => {} |
379 | } | 494 | } |
380 | } | 495 | } |
@@ -394,6 +509,49 @@ impl Ty { | |||
394 | _ => None, | 509 | _ => None, |
395 | } | 510 | } |
396 | } | 511 | } |
512 | |||
513 | /// If this is a type with type parameters (an ADT or function), replaces | ||
514 | /// the `Substs` for these type parameters with the given ones. (So e.g. if | ||
515 | /// `self` is `Option<_>` and the substs contain `u32`, we'll have | ||
516 | /// `Option<u32>` afterwards.) | ||
517 | pub fn apply_substs(self, substs: Substs) -> Ty { | ||
518 | match self { | ||
519 | Ty::Adt { def_id, name, .. } => Ty::Adt { | ||
520 | def_id, | ||
521 | name, | ||
522 | substs, | ||
523 | }, | ||
524 | _ => self, | ||
525 | } | ||
526 | } | ||
527 | |||
528 | /// Replaces type parameters in this type using the given `Substs`. (So e.g. | ||
529 | /// if `self` is `&[T]`, where type parameter T has index 0, and the | ||
530 | /// `Substs` contain `u32` at index 0, we'll have `&[u32]` afterwards.) | ||
531 | pub fn subst(self, substs: &Substs) -> Ty { | ||
532 | self.fold(&mut |ty| match ty { | ||
533 | Ty::Param { idx, name } => { | ||
534 | if (idx as usize) < substs.0.len() { | ||
535 | substs.0[idx as usize].clone() | ||
536 | } else { | ||
537 | // TODO: does this indicate a bug? i.e. should we always | ||
538 | // have substs for all type params? (they might contain the | ||
539 | // params themselves again...) | ||
540 | Ty::Param { idx, name } | ||
541 | } | ||
542 | } | ||
543 | ty => ty, | ||
544 | }) | ||
545 | } | ||
546 | |||
547 | /// Returns the type parameters of this type if it has some (i.e. is an ADT | ||
548 | /// or function); so if `self` is `Option<u32>`, this returns the `u32`. | ||
549 | fn substs(&self) -> Option<Substs> { | ||
550 | match self { | ||
551 | Ty::Adt { substs, .. } => Some(substs.clone()), | ||
552 | _ => None, | ||
553 | } | ||
554 | } | ||
397 | } | 555 | } |
398 | 556 | ||
399 | impl fmt::Display for Ty { | 557 | impl fmt::Display for Ty { |
@@ -425,7 +583,17 @@ impl fmt::Display for Ty { | |||
425 | .to_fmt(f)?; | 583 | .to_fmt(f)?; |
426 | write!(f, " -> {}", sig.output) | 584 | write!(f, " -> {}", sig.output) |
427 | } | 585 | } |
428 | Ty::Adt { name, .. } => write!(f, "{}", name), | 586 | Ty::Adt { name, substs, .. } => { |
587 | write!(f, "{}", name)?; | ||
588 | if substs.0.len() > 0 { | ||
589 | join(substs.0.iter()) | ||
590 | .surround_with("<", ">") | ||
591 | .separator(", ") | ||
592 | .to_fmt(f)?; | ||
593 | } | ||
594 | Ok(()) | ||
595 | } | ||
596 | Ty::Param { name, .. } => write!(f, "{}", name), | ||
429 | Ty::Unknown => write!(f, "[unknown]"), | 597 | Ty::Unknown => write!(f, "[unknown]"), |
430 | Ty::Infer(..) => write!(f, "_"), | 598 | Ty::Infer(..) => write!(f, "_"), |
431 | } | 599 | } |
@@ -440,28 +608,49 @@ fn type_for_fn(db: &impl HirDatabase, f: Function) -> Ty { | |||
440 | let signature = f.signature(db); | 608 | let signature = f.signature(db); |
441 | let module = f.module(db); | 609 | let module = f.module(db); |
442 | let impl_block = f.impl_block(db); | 610 | let impl_block = f.impl_block(db); |
443 | // TODO we ignore type parameters for now | 611 | let generics = f.generic_params(db); |
444 | let input = signature | 612 | let input = signature |
445 | .params() | 613 | .params() |
446 | .iter() | 614 | .iter() |
447 | .map(|tr| Ty::from_hir(db, &module, impl_block.as_ref(), tr)) | 615 | .map(|tr| Ty::from_hir(db, &module, impl_block.as_ref(), &generics, tr)) |
448 | .collect::<Vec<_>>(); | 616 | .collect::<Vec<_>>(); |
449 | let output = Ty::from_hir(db, &module, impl_block.as_ref(), signature.ret_type()); | 617 | let output = Ty::from_hir( |
618 | db, | ||
619 | &module, | ||
620 | impl_block.as_ref(), | ||
621 | &generics, | ||
622 | signature.ret_type(), | ||
623 | ); | ||
450 | let sig = FnSig { input, output }; | 624 | let sig = FnSig { input, output }; |
451 | Ty::FnPtr(Arc::new(sig)) | 625 | Ty::FnPtr(Arc::new(sig)) |
452 | } | 626 | } |
453 | 627 | ||
628 | fn make_substs(generics: &GenericParams) -> Substs { | ||
629 | Substs( | ||
630 | generics | ||
631 | .params | ||
632 | .iter() | ||
633 | .map(|_p| Ty::Unknown) | ||
634 | .collect::<Vec<_>>() | ||
635 | .into(), | ||
636 | ) | ||
637 | } | ||
638 | |||
454 | fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { | 639 | fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { |
640 | let generics = s.generic_params(db); | ||
455 | Ty::Adt { | 641 | Ty::Adt { |
456 | def_id: s.def_id(), | 642 | def_id: s.def_id(), |
457 | name: s.name(db).unwrap_or_else(Name::missing), | 643 | name: s.name(db).unwrap_or_else(Name::missing), |
644 | substs: make_substs(&generics), | ||
458 | } | 645 | } |
459 | } | 646 | } |
460 | 647 | ||
461 | pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { | 648 | pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { |
649 | let generics = s.generic_params(db); | ||
462 | Ty::Adt { | 650 | Ty::Adt { |
463 | def_id: s.def_id(), | 651 | def_id: s.def_id(), |
464 | name: s.name(db).unwrap_or_else(Name::missing), | 652 | name: s.name(db).unwrap_or_else(Name::missing), |
653 | substs: make_substs(&generics), | ||
465 | } | 654 | } |
466 | } | 655 | } |
467 | 656 | ||
@@ -495,9 +684,9 @@ pub(super) fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Ty { | |||
495 | 684 | ||
496 | pub(super) fn type_for_field(db: &impl HirDatabase, def_id: DefId, field: Name) -> Option<Ty> { | 685 | pub(super) fn type_for_field(db: &impl HirDatabase, def_id: DefId, field: Name) -> Option<Ty> { |
497 | let def = def_id.resolve(db); | 686 | let def = def_id.resolve(db); |
498 | let variant_data = match def { | 687 | let (variant_data, generics) = match def { |
499 | Def::Struct(s) => s.variant_data(db), | 688 | Def::Struct(s) => (s.variant_data(db), s.generic_params(db)), |
500 | Def::EnumVariant(ev) => ev.variant_data(db), | 689 | Def::EnumVariant(ev) => (ev.variant_data(db), ev.parent_enum(db).generic_params(db)), |
501 | // TODO: unions | 690 | // TODO: unions |
502 | _ => panic!( | 691 | _ => panic!( |
503 | "trying to get type for field in non-struct/variant {:?}", | 692 | "trying to get type for field in non-struct/variant {:?}", |
@@ -507,7 +696,13 @@ pub(super) fn type_for_field(db: &impl HirDatabase, def_id: DefId, field: Name) | |||
507 | let module = def_id.module(db); | 696 | let module = def_id.module(db); |
508 | let impl_block = def_id.impl_block(db); | 697 | let impl_block = def_id.impl_block(db); |
509 | let type_ref = variant_data.get_field_type_ref(&field)?; | 698 | let type_ref = variant_data.get_field_type_ref(&field)?; |
510 | Some(Ty::from_hir(db, &module, impl_block.as_ref(), &type_ref)) | 699 | Some(Ty::from_hir( |
700 | db, | ||
701 | &module, | ||
702 | impl_block.as_ref(), | ||
703 | &generics, | ||
704 | &type_ref, | ||
705 | )) | ||
511 | } | 706 | } |
512 | 707 | ||
513 | /// The result of type inference: A mapping from expressions and patterns to types. | 708 | /// The result of type inference: A mapping from expressions and patterns to types. |
@@ -684,8 +879,26 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
684 | self.type_of_pat.insert(pat, ty); | 879 | self.type_of_pat.insert(pat, ty); |
685 | } | 880 | } |
686 | 881 | ||
687 | fn make_ty(&self, type_ref: &TypeRef) -> Ty { | 882 | fn make_ty(&mut self, type_ref: &TypeRef) -> Ty { |
688 | Ty::from_hir(self.db, &self.module, self.impl_block.as_ref(), type_ref) | 883 | // TODO provide generics of function |
884 | let generics = GenericParams::default(); | ||
885 | let ty = Ty::from_hir( | ||
886 | self.db, | ||
887 | &self.module, | ||
888 | self.impl_block.as_ref(), | ||
889 | &generics, | ||
890 | type_ref, | ||
891 | ); | ||
892 | let ty = self.insert_type_vars(ty); | ||
893 | ty | ||
894 | } | ||
895 | |||
896 | fn unify_substs(&mut self, substs1: &Substs, substs2: &Substs) -> bool { | ||
897 | substs1 | ||
898 | .0 | ||
899 | .iter() | ||
900 | .zip(substs2.0.iter()) | ||
901 | .all(|(t1, t2)| self.unify(t1, t2)) | ||
689 | } | 902 | } |
690 | 903 | ||
691 | fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { | 904 | fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { |
@@ -708,12 +921,16 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
708 | (Ty::Bool, _) | (Ty::Str, _) | (Ty::Never, _) | (Ty::Char, _) => ty1 == ty2, | 921 | (Ty::Bool, _) | (Ty::Str, _) | (Ty::Never, _) | (Ty::Char, _) => ty1 == ty2, |
709 | ( | 922 | ( |
710 | Ty::Adt { | 923 | Ty::Adt { |
711 | def_id: def_id1, .. | 924 | def_id: def_id1, |
925 | substs: substs1, | ||
926 | .. | ||
712 | }, | 927 | }, |
713 | Ty::Adt { | 928 | Ty::Adt { |
714 | def_id: def_id2, .. | 929 | def_id: def_id2, |
930 | substs: substs2, | ||
931 | .. | ||
715 | }, | 932 | }, |
716 | ) if def_id1 == def_id2 => true, | 933 | ) if def_id1 == def_id2 => self.unify_substs(substs1, substs2), |
717 | (Ty::Slice(t1), Ty::Slice(t2)) => self.unify(t1, t2), | 934 | (Ty::Slice(t1), Ty::Slice(t2)) => self.unify(t1, t2), |
718 | (Ty::RawPtr(t1, m1), Ty::RawPtr(t2, m2)) if m1 == m2 => self.unify(t1, t2), | 935 | (Ty::RawPtr(t1, m1), Ty::RawPtr(t2, m2)) if m1 == m2 => self.unify(t1, t2), |
719 | (Ty::Ref(t1, m1), Ty::Ref(t2, m2)) if m1 == m2 => self.unify(t1, t2), | 936 | (Ty::Ref(t1, m1), Ty::Ref(t2, m2)) if m1 == m2 => self.unify(t1, t2), |
@@ -848,73 +1065,100 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
848 | Some(ty) | 1065 | Some(ty) |
849 | } | 1066 | } |
850 | 1067 | ||
851 | fn resolve_variant(&self, path: Option<&Path>) -> (Ty, Option<DefId>) { | 1068 | fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<DefId>) { |
852 | let path = if let Some(path) = path { | 1069 | let path = match path { |
853 | path | 1070 | Some(path) => path, |
854 | } else { | 1071 | None => return (Ty::Unknown, None), |
855 | return (Ty::Unknown, None); | ||
856 | }; | 1072 | }; |
857 | let def_id = if let Some(def_id) = self.module.resolve_path(self.db, &path).take_types() { | 1073 | let def_id = match self.module.resolve_path(self.db, &path).take_types() { |
858 | def_id | 1074 | Some(def_id) => def_id, |
859 | } else { | 1075 | _ => return (Ty::Unknown, None), |
860 | return (Ty::Unknown, None); | ||
861 | }; | 1076 | }; |
1077 | // TODO remove the duplication between here and `Ty::from_path`? | ||
1078 | // TODO provide generics of function | ||
1079 | let generics = GenericParams::default(); | ||
1080 | let substs = Ty::substs_from_path( | ||
1081 | self.db, | ||
1082 | &self.module, | ||
1083 | self.impl_block.as_ref(), | ||
1084 | &generics, | ||
1085 | path, | ||
1086 | def_id, | ||
1087 | ); | ||
862 | match def_id.resolve(self.db) { | 1088 | match def_id.resolve(self.db) { |
863 | Def::Struct(s) => { | 1089 | Def::Struct(s) => { |
864 | let ty = type_for_struct(self.db, s); | 1090 | let ty = type_for_struct(self.db, s); |
1091 | let ty = self.insert_type_vars(ty.apply_substs(substs)); | ||
865 | (ty, Some(def_id)) | 1092 | (ty, Some(def_id)) |
866 | } | 1093 | } |
867 | Def::EnumVariant(ev) => { | 1094 | Def::EnumVariant(ev) => { |
868 | let ty = type_for_enum_variant(self.db, ev); | 1095 | let ty = type_for_enum_variant(self.db, ev); |
1096 | let ty = self.insert_type_vars(ty.apply_substs(substs)); | ||
869 | (ty, Some(def_id)) | 1097 | (ty, Some(def_id)) |
870 | } | 1098 | } |
871 | _ => (Ty::Unknown, None), | 1099 | _ => (Ty::Unknown, None), |
872 | } | 1100 | } |
873 | } | 1101 | } |
874 | 1102 | ||
875 | fn resolve_fields(&self, path: Option<&Path>) -> Option<(Ty, Vec<StructField>)> { | 1103 | fn resolve_fields(&mut self, path: Option<&Path>) -> Option<(Ty, Vec<StructField>)> { |
876 | let def_id = self.module.resolve_path(self.db, path?).take_types()?; | 1104 | let (ty, def_id) = self.resolve_variant(path); |
1105 | let def_id = def_id?; | ||
877 | let def = def_id.resolve(self.db); | 1106 | let def = def_id.resolve(self.db); |
878 | 1107 | ||
879 | match def { | 1108 | match def { |
880 | Def::Struct(s) => { | 1109 | Def::Struct(s) => { |
881 | let fields = s.fields(self.db); | 1110 | let fields = s.fields(self.db); |
882 | Some((type_for_struct(self.db, s), fields)) | 1111 | Some((ty, fields)) |
883 | } | 1112 | } |
884 | Def::EnumVariant(ev) => { | 1113 | Def::EnumVariant(ev) => { |
885 | let fields = ev.fields(self.db); | 1114 | let fields = ev.fields(self.db); |
886 | Some((type_for_enum_variant(self.db, ev), fields)) | 1115 | Some((ty, fields)) |
887 | } | 1116 | } |
888 | _ => None, | 1117 | _ => None, |
889 | } | 1118 | } |
890 | } | 1119 | } |
891 | 1120 | ||
892 | fn infer_tuple_struct_pat(&mut self, path: Option<&Path>, subpats: &[PatId]) -> Ty { | 1121 | fn infer_tuple_struct_pat( |
1122 | &mut self, | ||
1123 | path: Option<&Path>, | ||
1124 | subpats: &[PatId], | ||
1125 | expected: &Ty, | ||
1126 | ) -> Ty { | ||
893 | let (ty, fields) = self | 1127 | let (ty, fields) = self |
894 | .resolve_fields(path) | 1128 | .resolve_fields(path) |
895 | .unwrap_or((Ty::Unknown, Vec::new())); | 1129 | .unwrap_or((Ty::Unknown, Vec::new())); |
896 | 1130 | ||
1131 | self.unify(&ty, expected); | ||
1132 | |||
1133 | let substs = ty.substs().expect("adt should have substs"); | ||
1134 | |||
897 | for (i, &subpat) in subpats.iter().enumerate() { | 1135 | for (i, &subpat) in subpats.iter().enumerate() { |
898 | let expected_ty = fields | 1136 | let expected_ty = fields |
899 | .get(i) | 1137 | .get(i) |
900 | .and_then(|field| field.ty(self.db)) | 1138 | .and_then(|field| field.ty(self.db)) |
901 | .unwrap_or(Ty::Unknown); | 1139 | .unwrap_or(Ty::Unknown) |
1140 | .subst(&substs); | ||
902 | self.infer_pat(subpat, &expected_ty); | 1141 | self.infer_pat(subpat, &expected_ty); |
903 | } | 1142 | } |
904 | 1143 | ||
905 | ty | 1144 | ty |
906 | } | 1145 | } |
907 | 1146 | ||
908 | fn infer_struct_pat(&mut self, path: Option<&Path>, subpats: &[FieldPat]) -> Ty { | 1147 | fn infer_struct_pat(&mut self, path: Option<&Path>, subpats: &[FieldPat], expected: &Ty) -> Ty { |
909 | let (ty, fields) = self | 1148 | let (ty, fields) = self |
910 | .resolve_fields(path) | 1149 | .resolve_fields(path) |
911 | .unwrap_or((Ty::Unknown, Vec::new())); | 1150 | .unwrap_or((Ty::Unknown, Vec::new())); |
912 | 1151 | ||
1152 | self.unify(&ty, expected); | ||
1153 | |||
1154 | let substs = ty.substs().expect("adt should have substs"); | ||
1155 | |||
913 | for subpat in subpats { | 1156 | for subpat in subpats { |
914 | let matching_field = fields.iter().find(|field| field.name() == &subpat.name); | 1157 | let matching_field = fields.iter().find(|field| field.name() == &subpat.name); |
915 | let expected_ty = matching_field | 1158 | let expected_ty = matching_field |
916 | .and_then(|field| field.ty(self.db)) | 1159 | .and_then(|field| field.ty(self.db)) |
917 | .unwrap_or(Ty::Unknown); | 1160 | .unwrap_or(Ty::Unknown) |
1161 | .subst(&substs); | ||
918 | self.infer_pat(subpat.pat, &expected_ty); | 1162 | self.infer_pat(subpat.pat, &expected_ty); |
919 | } | 1163 | } |
920 | 1164 | ||
@@ -959,11 +1203,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
959 | Pat::TupleStruct { | 1203 | Pat::TupleStruct { |
960 | path: ref p, | 1204 | path: ref p, |
961 | args: ref subpats, | 1205 | args: ref subpats, |
962 | } => self.infer_tuple_struct_pat(p.as_ref(), subpats), | 1206 | } => self.infer_tuple_struct_pat(p.as_ref(), subpats, expected), |
963 | Pat::Struct { | 1207 | Pat::Struct { |
964 | path: ref p, | 1208 | path: ref p, |
965 | args: ref fields, | 1209 | args: ref fields, |
966 | } => self.infer_struct_pat(p.as_ref(), fields), | 1210 | } => self.infer_struct_pat(p.as_ref(), fields, expected), |
967 | Pat::Path(path) => self | 1211 | Pat::Path(path) => self |
968 | .module | 1212 | .module |
969 | .resolve_path(self.db, &path) | 1213 | .resolve_path(self.db, &path) |
@@ -1155,11 +1399,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1155 | spread, | 1399 | spread, |
1156 | } => { | 1400 | } => { |
1157 | let (ty, def_id) = self.resolve_variant(path.as_ref()); | 1401 | let (ty, def_id) = self.resolve_variant(path.as_ref()); |
1402 | let substs = ty.substs().expect("adt should have substs"); | ||
1158 | for field in fields { | 1403 | for field in fields { |
1159 | let field_ty = if let Some(def_id) = def_id { | 1404 | let field_ty = if let Some(def_id) = def_id { |
1160 | self.db | 1405 | self.db |
1161 | .type_for_field(def_id, field.name.clone()) | 1406 | .type_for_field(def_id, field.name.clone()) |
1162 | .unwrap_or(Ty::Unknown) | 1407 | .unwrap_or(Ty::Unknown) |
1408 | .subst(&substs) | ||
1163 | } else { | 1409 | } else { |
1164 | Ty::Unknown | 1410 | Ty::Unknown |
1165 | }; | 1411 | }; |
@@ -1180,7 +1426,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1180 | let i = name.to_string().parse::<usize>().ok(); | 1426 | let i = name.to_string().parse::<usize>().ok(); |
1181 | i.and_then(|i| fields.get(i).cloned()) | 1427 | i.and_then(|i| fields.get(i).cloned()) |
1182 | } | 1428 | } |
1183 | Ty::Adt { def_id, .. } => self.db.type_for_field(def_id, name.clone()), | 1429 | Ty::Adt { |
1430 | def_id, ref substs, .. | ||
1431 | } => self | ||
1432 | .db | ||
1433 | .type_for_field(def_id, name.clone()) | ||
1434 | .map(|ty| ty.subst(substs)), | ||
1184 | _ => None, | 1435 | _ => None, |
1185 | }) | 1436 | }) |
1186 | .unwrap_or(Ty::Unknown); | 1437 | .unwrap_or(Ty::Unknown); |
@@ -1193,7 +1444,6 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1193 | Expr::Cast { expr, type_ref } => { | 1444 | Expr::Cast { expr, type_ref } => { |
1194 | let _inner_ty = self.infer_expr(*expr, &Expectation::none()); | 1445 | let _inner_ty = self.infer_expr(*expr, &Expectation::none()); |
1195 | let cast_ty = self.make_ty(type_ref); | 1446 | let cast_ty = self.make_ty(type_ref); |
1196 | let cast_ty = self.insert_type_vars(cast_ty); | ||
1197 | // TODO check the cast... | 1447 | // TODO check the cast... |
1198 | cast_ty | 1448 | cast_ty |
1199 | } | 1449 | } |
@@ -1305,12 +1555,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1305 | type_ref, | 1555 | type_ref, |
1306 | initializer, | 1556 | initializer, |
1307 | } => { | 1557 | } => { |
1308 | let decl_ty = Ty::from_hir_opt( | 1558 | let decl_ty = type_ref |
1309 | self.db, | 1559 | .as_ref() |
1310 | &self.module, | 1560 | .map(|tr| self.make_ty(tr)) |
1311 | self.impl_block.as_ref(), | 1561 | .unwrap_or(Ty::Unknown); |
1312 | type_ref.as_ref(), | ||
1313 | ); | ||
1314 | let decl_ty = self.insert_type_vars(decl_ty); | 1562 | let decl_ty = self.insert_type_vars(decl_ty); |
1315 | let ty = if let Some(expr) = initializer { | 1563 | let ty = if let Some(expr) = initializer { |
1316 | let expr_ty = self.infer_expr(*expr, &Expectation::has_type(decl_ty)); | 1564 | let expr_ty = self.infer_expr(*expr, &Expectation::has_type(decl_ty)); |
@@ -1338,13 +1586,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1338 | let body = Arc::clone(&self.body); // avoid borrow checker problem | 1586 | let body = Arc::clone(&self.body); // avoid borrow checker problem |
1339 | for (type_ref, pat) in signature.params().iter().zip(body.params()) { | 1587 | for (type_ref, pat) in signature.params().iter().zip(body.params()) { |
1340 | let ty = self.make_ty(type_ref); | 1588 | let ty = self.make_ty(type_ref); |
1341 | let ty = self.insert_type_vars(ty); | ||
1342 | 1589 | ||
1343 | self.infer_pat(*pat, &ty); | 1590 | self.infer_pat(*pat, &ty); |
1344 | } | 1591 | } |
1345 | self.return_ty = { | 1592 | self.return_ty = { |
1346 | let ty = self.make_ty(signature.ret_type()); | 1593 | let ty = self.make_ty(signature.ret_type()); |
1347 | let ty = self.insert_type_vars(ty); | ||
1348 | ty | 1594 | ty |
1349 | }; | 1595 | }; |
1350 | } | 1596 | } |