@@ -399,13 +399,13 @@ static auto TryAsClassScope(Context& context, SemIR::NameScopeId scope_id)
399399 return context.insts ().TryGetAs <SemIR::ClassDecl>(scope.inst_id ());
400400}
401401
402- // Process an `extend impl` declaration by extending the impl scope with the
403- // `impl`'s scope .
404- static auto ExtendImpl (Context& context, Parse::NodeId extend_node,
405- SemIR::LocId loc_id, SemIR::ImplId impl_id,
406- SemIR::LocId implicit_params_loc_id,
407- SemIR::TypeInstId constraint_type_inst_id,
408- SemIR::TypeId constraint_type_id) -> bool {
402+ // Apply an `extend impl` declaration by extending the parent scope with the
403+ // `impl`. If there 's an error it is diagnosed and false is returned .
404+ static auto ApplyExtendImplAs (Context& context, Parse::NodeId extend_node,
405+ SemIR::LocId loc_id, SemIR::ImplId impl_id,
406+ SemIR::LocId implicit_params_loc_id,
407+ SemIR::TypeInstId constraint_type_inst_id)
408+ -> bool {
409409 auto parent_scope_id = context.decl_name_stack ().PeekParentScopeId ();
410410 if (!parent_scope_id.has_value ()) {
411411 DiagnoseExtendImplOutsideClass (context, loc_id);
@@ -432,6 +432,8 @@ static auto ExtendImpl(Context& context, Parse::NodeId extend_node,
432432 if (impl.witness_id == SemIR::ErrorInst::InstId) {
433433 parent_scope.set_has_error ();
434434 } else {
435+ auto constraint_type_id =
436+ context.types ().GetTypeIdForTypeInstId (constraint_type_inst_id);
435437 bool is_complete = RequireCompleteType (
436438 context, constraint_type_id, SemIR::LocId (constraint_type_inst_id),
437439 [&] {
@@ -484,11 +486,10 @@ static auto DiagnoseUnusedGenericBinding(Context& context, SemIR::LocId loc_id,
484486 FillImplWitnessWithErrors (context, context.impls ().Get (impl_id));
485487}
486488
487- auto StartImplDecl (Context& context, SemIR::LocId loc_id,
488- SemIR::LocId implicit_params_loc_id, SemIR::Impl impl,
489- bool is_definition,
490- std::optional<ExtendImplDecl> extend_impl)
491- -> std::pair<SemIR::ImplId, SemIR::InstId> {
489+ auto GetOrAddImpl (Context& context, SemIR::LocId loc_id,
490+ SemIR::LocId implicit_params_loc_id, SemIR::Impl impl,
491+ bool is_definition, Parse::NodeId extend_node)
492+ -> SemIR::ImplId {
492493 auto impl_id = SemIR::ImplId::None;
493494
494495 // Add the impl declaration.
@@ -500,72 +501,70 @@ auto StartImplDecl(Context& context, SemIR::LocId loc_id,
500501 if (IsValidImplRedecl (context, impl, prev_impl_id)) {
501502 impl_id = prev_impl_id;
502503 } else {
503- // IsValidImplRedecl() has issued a diagnostic, avoid generating more
504- // diagnostics for this declaration.
504+ // IsValidImplRedecl() has issued a diagnostic, take care to avoid
505+ // generating more diagnostics for this declaration.
505506 impl.witness_id = SemIR::ErrorInst::InstId;
506507 }
507508 break ;
508509 }
509510 }
510511
511- // Create a new impl if this isn't a valid redeclaration.
512- if (!impl_id.has_value ()) {
513- impl.generic_id = BuildGeneric (context, impl.latest_decl_id ());
514- if (impl.witness_id != SemIR::ErrorInst::InstId) {
515- if (impl.interface .interface_id .has_value ()) {
516- impl.witness_id =
517- ImplWitnessForDeclaration (context, impl, is_definition);
518- } else {
519- impl.witness_id = SemIR::ErrorInst::InstId;
520- // TODO: We might also want to mark that the name scope for the impl has
521- // an error -- at least once we start making name lookups within the
522- // impl also look into the facet (eg, so you can name associated
523- // constants from within the impl).
524- }
512+ if (impl_id.has_value ()) {
513+ // This is a redeclaration of another impl, now held in `impl_id`.
514+ auto & prev_impl = context.impls ().Get (impl_id);
515+ FinishGenericRedecl (context, prev_impl.generic_id );
516+ return impl_id;
517+ }
518+
519+ // This is a new declaration (possibly with an attached definition). Create a
520+ // new `impl_id`, filling the missing generic and witness in the provided
521+ // `Impl`.
522+
523+ impl.generic_id = BuildGeneric (context, impl.latest_decl_id ());
524+ if (impl.witness_id != SemIR::ErrorInst::InstId) {
525+ if (impl.interface .interface_id .has_value ()) {
526+ impl.witness_id = ImplWitnessForDeclaration (context, impl, is_definition);
527+ } else {
528+ impl.witness_id = SemIR::ErrorInst::InstId;
529+ // TODO: We might also want to mark that the name scope for the impl has
530+ // an error -- at least once we start making name lookups within the
531+ // impl also look into the facet (eg, so you can name associated
532+ // constants from within the impl).
525533 }
526- FinishGenericDecl (context, SemIR::LocId (impl.latest_decl_id ()),
527- impl.generic_id );
528- // From here on, use the `Impl` from the `ImplStore` instead of `impl`
529- // in order to make and see any changes to the `Impl`.
530- impl_id = context.impls ().Add (impl);
531- lookup_bucket_ref.push_back (impl_id);
532-
533- AssignImplIdInWitness (context, impl_id, impl.witness_id );
534-
535- // Looking to see if there are any generic bindings on the `impl`
536- // declaration that are not deducible. If so, and the `impl` does not
537- // actually use all its generic bindings, and will never be matched. This
538- // should be diagnossed to the user.
539- bool has_error_in_implicit_pattern = false ;
540- if (impl.implicit_param_patterns_id .has_value ()) {
541- for (auto inst_id :
542- context.inst_blocks ().Get (impl.implicit_param_patterns_id )) {
543- if (inst_id == SemIR::ErrorInst::InstId) {
544- has_error_in_implicit_pattern = true ;
545- break ;
546- }
534+ }
535+ FinishGenericDecl (context, SemIR::LocId (impl.latest_decl_id ()),
536+ impl.generic_id );
537+ // From here on, use the `Impl` from the `ImplStore` instead of `impl`
538+ // in order to make and see any changes to the `Impl`.
539+ impl_id = context.impls ().Add (impl);
540+ lookup_bucket_ref.push_back (impl_id);
541+
542+ AssignImplIdInWitness (context, impl_id, impl.witness_id );
543+
544+ auto & stored_impl_info = context.impls ().Get (impl_id);
545+
546+ // Looking to see if there are any generic bindings on the `impl`
547+ // declaration that are not deducible. If so, and the `impl` does not
548+ // actually use all its generic bindings, and will never be matched. This
549+ // should be diagnossed to the user.
550+ bool has_error_in_implicit_pattern = false ;
551+ if (impl.implicit_param_patterns_id .has_value ()) {
552+ for (auto inst_id :
553+ context.inst_blocks ().Get (impl.implicit_param_patterns_id )) {
554+ if (inst_id == SemIR::ErrorInst::InstId) {
555+ has_error_in_implicit_pattern = true ;
556+ break ;
547557 }
548558 }
549-
550- if (!has_error_in_implicit_pattern) {
551- DiagnoseUnusedGenericBinding (context, loc_id, implicit_params_loc_id,
552- impl_id);
553- }
554- } else {
555- auto & stored_impl = context.impls ().Get (impl_id);
556- FinishGenericRedecl (context, stored_impl.generic_id );
557559 }
558560
559- // Write the impl ID into the ImplDecl.
560- auto impl_decl =
561- context.insts ().GetAs <SemIR::ImplDecl>(impl.first_owning_decl_id );
562- CARBON_CHECK (!impl_decl.impl_id .has_value ());
563- impl_decl.impl_id = impl_id;
564- ReplaceInstBeforeConstantUse (context, impl.first_owning_decl_id , impl_decl);
561+ if (!has_error_in_implicit_pattern) {
562+ DiagnoseUnusedGenericBinding (context, loc_id, implicit_params_loc_id,
563+ impl_id);
564+ }
565565
566566 // For an `extend impl` declaration, mark the impl as extending this `impl`.
567- if (extend_impl) {
568- auto & stored_impl_info = context.impls ().Get (impl_decl.impl_id );
567+ if (extend_node.has_value ()) {
569568 auto self_type_id =
570569 context.types ().GetTypeIdForTypeInstId (stored_impl_info.self_id );
571570 if (self_type_id != SemIR::ErrorInst::TypeId) {
@@ -578,9 +577,8 @@ auto StartImplDecl(Context& context, SemIR::LocId loc_id,
578577 .specific_id = context.generics ().GetSelfSpecific (
579578 stored_impl_info.generic_id )});
580579 }
581- if (!ExtendImpl (context, extend_impl->extend_node_id , loc_id,
582- impl_decl.impl_id , implicit_params_loc_id, constraint_id,
583- extend_impl->constraint_type_id )) {
580+ if (!ApplyExtendImplAs (context, extend_node, loc_id, impl_id,
581+ implicit_params_loc_id, constraint_id)) {
584582 // Don't allow the invalid impl to be used.
585583 FillImplWitnessWithErrors (context, stored_impl_info);
586584 }
@@ -598,7 +596,7 @@ auto StartImplDecl(Context& context, SemIR::LocId loc_id,
598596 }
599597 }
600598
601- return { impl_id, impl. latest_decl_id ()} ;
599+ return impl_id;
602600}
603601
604602} // namespace Carbon::Check
0 commit comments