diff --git a/dora-frontend/src/aliasck.rs b/dora-frontend/src/aliasck.rs index 86af9a8da..5a05fd089 100644 --- a/dora-frontend/src/aliasck.rs +++ b/dora-frontend/src/aliasck.rs @@ -132,7 +132,7 @@ fn expand_type( | SourceType::This | SourceType::TypeParam(..) => ty, - SourceType::GenericAssoc(..) | SourceType::Any | SourceType::Ptr => { + SourceType::GenericAssoc { .. } | SourceType::Any | SourceType::Ptr => { panic!("unexpected type = {:?}", ty); } } diff --git a/dora-frontend/src/extensiondefck.rs b/dora-frontend/src/extensiondefck.rs index a48fe4541..316b609ae 100644 --- a/dora-frontend/src/extensiondefck.rs +++ b/dora-frontend/src/extensiondefck.rs @@ -78,7 +78,7 @@ pub fn package_for_type(sa: &Sema, ty: SourceType) -> Option Some(sa.enum_(id).package_id), SourceType::TraitObject(id, ..) => Some(sa.trait_(id).package_id), SourceType::Alias(id, ..) => Some(sa.alias(id).package_id), - SourceType::Assoc(..) | SourceType::GenericAssoc(..) => unimplemented!(), + SourceType::Assoc(..) | SourceType::GenericAssoc { .. } => unimplemented!(), } } @@ -106,7 +106,7 @@ impl<'x> ExtensionCheck<'x> { | SourceType::Ptr | SourceType::This | SourceType::Assoc(..) - | SourceType::GenericAssoc(..) => { + | SourceType::GenericAssoc { .. } => { unreachable!() } SourceType::Error @@ -243,7 +243,7 @@ fn discover_type_params(sa: &Sema, ty: SourceType, used_type_params: &mut FixedB SourceType::TypeParam(tp_id) => { used_type_params.insert(tp_id.index()); } - SourceType::Alias(..) | SourceType::Assoc(..) | SourceType::GenericAssoc(..) => { + SourceType::Alias(..) | SourceType::Assoc(..) | SourceType::GenericAssoc { .. } => { unreachable!() } } diff --git a/dora-frontend/src/impldefck.rs b/dora-frontend/src/impldefck.rs index d0ace8bfa..b47ea6062 100644 --- a/dora-frontend/src/impldefck.rs +++ b/dora-frontend/src/impldefck.rs @@ -21,7 +21,7 @@ fn check_impl_definition(sa: &Sema, impl_: &ImplDefinition) { | SourceType::Ptr | SourceType::This | SourceType::Assoc(..) - | SourceType::GenericAssoc(..) => { + | SourceType::GenericAssoc { .. } => { unreachable!() } SourceType::Error @@ -424,7 +424,7 @@ fn trait_and_impl_arg_ty_compatible( SourceType::Alias(..) | SourceType::Any | SourceType::Ptr - | SourceType::GenericAssoc(..) => unreachable!(), + | SourceType::GenericAssoc { .. } => unreachable!(), } } diff --git a/dora-frontend/src/parsety.rs b/dora-frontend/src/parsety.rs index 89cd15e14..94802d2b5 100644 --- a/dora-frontend/src/parsety.rs +++ b/dora-frontend/src/parsety.rs @@ -105,7 +105,8 @@ pub enum ParsedTypeKind { This, Regular { - symbol: SymbolKind, + symbol: Option, + kind: Option, type_arguments: Vec, }, @@ -184,7 +185,8 @@ fn parse_trait_type_inner( match &parsed_ast.kind { ParsedTypeKind::Regular { - symbol: SymbolKind::Trait(trait_id), + symbol: Some(SymbolKind::Trait(trait_id)), + kind: None, type_arguments, } => { let trait_ty = @@ -237,15 +239,15 @@ fn parse_type_regular( allow_self: bool, node: &ast::TypeRegularType, ) -> ParsedTypeKind { - let segment_kind = parse_path(sa, table, file_id, element, allow_self, node); + let path_kind = parse_path(sa, table, file_id, element, allow_self, node); - if segment_kind.is_err() { + if path_kind.is_err() { return ParsedTypeKind::Error; } - let segment_kind = segment_kind.unwrap(); + let path_kind = path_kind.unwrap(); - match segment_kind { + match path_kind { PathKind::Symbol(sym) => match sym { SymbolKind::Trait(..) | SymbolKind::Class(..) @@ -262,7 +264,8 @@ fn parse_type_regular( } ParsedTypeKind::Regular { - symbol: sym, + symbol: Some(sym), + kind: None, type_arguments: Vec::new(), } } @@ -274,6 +277,12 @@ fn parse_type_regular( } }, + PathKind::GenericAssoc { .. } => ParsedTypeKind::Regular { + symbol: None, + kind: Some(path_kind), + type_arguments: Vec::new(), + }, + PathKind::Self_ => ParsedTypeKind::This, } } @@ -306,7 +315,8 @@ fn parse_type_regular_with_arguments( } ParsedTypeKind::Regular { - symbol, + symbol: Some(symbol), + kind: None, type_arguments, } } @@ -369,8 +379,9 @@ fn convert_type_regular(sa: &Sema, file_id: SourceFileId, parsed_ty: &ParsedType let (sym, type_params) = match parsed_ty.kind { ParsedTypeKind::Regular { ref symbol, + kind: None, type_arguments: ref type_params, - } => (symbol.clone(), type_params), + } => (symbol.clone().expect("symbol expected"), type_params), _ => unreachable!(), }; @@ -660,7 +671,7 @@ fn check_type_inner( parsed_ty: &ParsedTypeAst, ) -> SourceType { match ty.clone() { - SourceType::Any | SourceType::Ptr | SourceType::GenericAssoc(..) => { + SourceType::Any | SourceType::Ptr | SourceType::GenericAssoc { .. } => { unreachable!() } SourceType::This => SourceType::This, @@ -676,7 +687,7 @@ fn check_type_inner( | SourceType::Int32 | SourceType::Int64 => { let symbol = match &parsed_ty.kind { - ParsedTypeKind::Regular { symbol, .. } => symbol.clone(), + ParsedTypeKind::Regular { symbol, .. } => symbol.clone().expect("symbol expected"), _ => unreachable!(), }; @@ -754,7 +765,7 @@ fn check_type_record( ref symbol, type_arguments: ref type_params, .. - } => (symbol.clone(), type_params), + } => (symbol.clone().expect("symbol expected"), type_params), _ => unreachable!(), }; @@ -1151,7 +1162,7 @@ fn expand_st( | SourceType::TypeParam(..) => ty, SourceType::This => replace_self.expect("self expected"), - SourceType::Any | SourceType::Ptr | SourceType::GenericAssoc(..) => { + SourceType::Any | SourceType::Ptr | SourceType::GenericAssoc { .. } => { panic!("unexpected type = {:?}", ty); // unreachable!() } diff --git a/dora-frontend/src/path.rs b/dora-frontend/src/path.rs index 08be99d62..c3aeefbe8 100644 --- a/dora-frontend/src/path.rs +++ b/dora-frontend/src/path.rs @@ -4,12 +4,19 @@ use dora_parser::{ast, Span}; use crate::access::sym_accessible_from; use crate::sema::{ - parent_element_or_self, AliasDefinitionId, Element, Sema, SourceFileId, TypeParamId, + parent_element_or_self, AliasDefinitionId, Element, Sema, SourceFileId, TraitDefinitionId, + TypeParamId, }; use crate::{ErrorMessage, ModuleSymTable, Name, SymbolKind}; +#[derive(Clone, Debug)] pub enum PathKind { Self_, + GenericAssoc { + tp_id: TypeParamId, + trait_id: TraitDefinitionId, + assoc_id: AliasDefinitionId, + }, Symbol(SymbolKind), } @@ -96,6 +103,7 @@ fn parse_path_ident( } let mut previous_sym = sym.expect("missing symbol"); + let mut result: Option = None; for (idx, segment) in segments.iter().enumerate().skip(1) { if previous_sym.is_module() { @@ -129,10 +137,17 @@ fn parse_path_ident( } else if let SymbolKind::TypeParam(id) = previous_sym { let name = expect_ident(sa, file_id, segment)?; - let avaiable = lookup_alias_on_type_param(sa, element, id, name).unwrap_or(Vec::new()); - - if avaiable.len() == 1 { - previous_sym = SymbolKind::Alias(avaiable[0]); + let mut available = + lookup_alias_on_type_param(sa, element, id, name).unwrap_or(Vec::new()); + + if available.len() == 1 { + let (trait_id, assoc_id) = available.pop().expect("element expected"); + previous_sym = SymbolKind::Alias(available[0].1); + result = Some(PathKind::GenericAssoc { + tp_id: id, + trait_id, + assoc_id, + }); } else { unimplemented!() } @@ -146,7 +161,11 @@ fn parse_path_ident( } } - Ok(PathKind::Symbol(previous_sym)) + if let Some(path_kind) = result { + Ok(path_kind) + } else { + Ok(PathKind::Symbol(previous_sym)) + } } fn available_aliases<'a>( @@ -174,7 +193,7 @@ fn lookup_alias_on_type_param<'a>( element: &'a dyn Element, id: TypeParamId, name: Name, -) -> Option> { +) -> Option> { let type_param_definition = element.type_param_definition(); let mut results = Vec::with_capacity(2); @@ -183,7 +202,7 @@ fn lookup_alias_on_type_param<'a>( let trait_ = sa.trait_(trait_id); if let Some(id) = trait_.alias_names().get(&name) { - results.push(*id); + results.push((trait_id, *id)); } } diff --git a/dora-frontend/src/sema/impl_matching.rs b/dora-frontend/src/sema/impl_matching.rs index 5c6c12e90..ff88dcf21 100644 --- a/dora-frontend/src/sema/impl_matching.rs +++ b/dora-frontend/src/sema/impl_matching.rs @@ -65,7 +65,7 @@ pub fn implements_trait( SourceType::TypeParam(tp_id) => check_type_param_defs.implements_trait(sa, tp_id, trait_ty), - SourceType::Alias(..) | SourceType::Assoc(..) | SourceType::GenericAssoc(..) => { + SourceType::Alias(..) | SourceType::Assoc(..) | SourceType::GenericAssoc { .. } => { unreachable!() } diff --git a/dora-frontend/src/sema/matching.rs b/dora-frontend/src/sema/matching.rs index 09d99a346..49f12f489 100644 --- a/dora-frontend/src/sema/matching.rs +++ b/dora-frontend/src/sema/matching.rs @@ -236,7 +236,7 @@ fn match_concrete_types( _ => false, }, - SourceType::Alias(..) | SourceType::Assoc(..) | SourceType::GenericAssoc(..) => { + SourceType::Alias(..) | SourceType::Assoc(..) | SourceType::GenericAssoc { .. } => { unimplemented!() } diff --git a/dora-frontend/src/specialize.rs b/dora-frontend/src/specialize.rs index efc455603..ed7836afc 100644 --- a/dora-frontend/src/specialize.rs +++ b/dora-frontend/src/specialize.rs @@ -103,7 +103,7 @@ pub fn replace_type( | SourceType::Float64 | SourceType::Error => ty, - SourceType::Any | SourceType::Ptr | SourceType::GenericAssoc(..) => unreachable!(), + SourceType::Any | SourceType::Ptr | SourceType::GenericAssoc { .. } => unreachable!(), } } @@ -221,7 +221,7 @@ pub fn specialize_ty_for_trait_object( | SourceType::Float64 | SourceType::Error => ty, - SourceType::This | SourceType::Any | SourceType::Ptr | SourceType::GenericAssoc(..) => { + SourceType::This | SourceType::Any | SourceType::Ptr | SourceType::GenericAssoc { .. } => { unreachable!() } } @@ -311,7 +311,7 @@ pub fn specialize_for_element( SourceType::Any | SourceType::Ptr | SourceType::Assoc(..) - | SourceType::GenericAssoc(..) => unreachable!(), + | SourceType::GenericAssoc { .. } => unreachable!(), } } diff --git a/dora-frontend/src/ty.rs b/dora-frontend/src/ty.rs index 26e4004ce..c77b0093b 100644 --- a/dora-frontend/src/ty.rs +++ b/dora-frontend/src/ty.rs @@ -154,7 +154,12 @@ pub enum SourceType { Assoc(AliasDefinitionId, SourceTypeArray), // Some associated type on type parameter (T::X). - GenericAssoc(TraitDefinitionId, AliasDefinitionId, SourceTypeArray), + GenericAssoc { + tp_id: TypeParamId, + trait_id: TraitDefinitionId, + assoc_id: AliasDefinitionId, + type_params: SourceTypeArray, + }, // Some lambda. Lambda(SourceTypeArray, Box), @@ -186,7 +191,7 @@ impl SourceType { SourceType::Class(..) => TyKind::Class, SourceType::Unit | SourceType::Tuple(..) => TyKind::Tuple, SourceType::Assoc(..) => TyKind::Assoc, - SourceType::GenericAssoc(..) => TyKind::GenericAssoc, + SourceType::GenericAssoc { .. } => TyKind::GenericAssoc, } } @@ -541,7 +546,7 @@ impl SourceType { *self == other } - SourceType::GenericAssoc(..) => unimplemented!(), + SourceType::GenericAssoc { .. } => unimplemented!(), } } @@ -559,7 +564,7 @@ impl SourceType { | SourceType::TraitObject(..) | SourceType::Lambda(..) | SourceType::TypeParam(_) => true, - SourceType::Alias(..) | SourceType::Assoc(..) | SourceType::GenericAssoc(..) => { + SourceType::Alias(..) | SourceType::Assoc(..) | SourceType::GenericAssoc { .. } => { unreachable!() } SourceType::Enum(_, params) @@ -645,7 +650,7 @@ impl SourceType { SourceType::Alias(..) | SourceType::TypeParam(_) | SourceType::Assoc(..) - | SourceType::GenericAssoc(..) => false, + | SourceType::GenericAssoc { .. } => false, } } } @@ -666,7 +671,7 @@ pub fn contains_self(sa: &Sema, ty: SourceType) -> bool { | SourceType::TypeParam(..) | SourceType::Assoc(..) => false, - SourceType::Alias(..) | SourceType::GenericAssoc(..) => { + SourceType::Alias(..) | SourceType::GenericAssoc { .. } => { unimplemented!() } SourceType::Class(_, params) @@ -1053,7 +1058,7 @@ impl<'a> SourceTypePrinter<'a> { } } - SourceType::GenericAssoc(..) => unimplemented!(), + SourceType::GenericAssoc { .. } => unimplemented!(), } } } diff --git a/dora-frontend/src/typeck/expr.rs b/dora-frontend/src/typeck/expr.rs index 7c609cdeb..30f2cfc4e 100644 --- a/dora-frontend/src/typeck/expr.rs +++ b/dora-frontend/src/typeck/expr.rs @@ -737,7 +737,7 @@ fn check_expr_assign_unnamed_field( | SourceType::Lambda(..) | SourceType::Alias(..) | SourceType::Assoc(..) - | SourceType::GenericAssoc(..) => { + | SourceType::GenericAssoc { .. } => { let name = index.to_string(); let expr_name = ck.ty_name(&object_type); let msg = ErrorMessage::UnknownField(name, expr_name); @@ -899,7 +899,7 @@ pub(super) fn check_expr_dot( | SourceType::Tuple(..) | SourceType::Alias(..) | SourceType::Assoc(..) - | SourceType::GenericAssoc(..) => {} + | SourceType::GenericAssoc { .. } => {} SourceType::Class(cls_id, class_type_params) => { if let Some((field_id, _)) = find_field_in_class(ck.sa, object_type.clone(), interned_name) @@ -989,7 +989,7 @@ fn check_expr_dot_unnamed_field( | SourceType::Lambda(..) | SourceType::Alias(..) | SourceType::Assoc(..) - | SourceType::GenericAssoc(..) => { + | SourceType::GenericAssoc { .. } => { let name = index.to_string(); let expr_name = ck.ty_name(&object_type); let msg = ErrorMessage::UnknownField(name, expr_name); diff --git a/dora-frontend/src/typeck/function.rs b/dora-frontend/src/typeck/function.rs index 858998f98..db0689f48 100644 --- a/dora-frontend/src/typeck/function.rs +++ b/dora-frontend/src/typeck/function.rs @@ -607,7 +607,7 @@ pub(super) fn arg_allows( arg_allows(sa, alias.ty(), arg, self_ty.clone()) } - SourceType::Assoc(..) | SourceType::GenericAssoc(..) => unimplemented!(), + SourceType::Assoc(..) | SourceType::GenericAssoc { .. } => unimplemented!(), } }